Coder Social home page Coder Social logo

recyclerview-flexibledivider's People

Contributors

intrications avatar ravidsrk avatar rbcum avatar sheungon avatar yqritc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

recyclerview-flexibledivider's Issues

why the divider color is not the same as that it should be?

Hi,
I use the API as the doc says:

recyclerView.addItemDecoration( new HorizontalDividerItemDecoration.Builder(this) .color(Color.RED) .sizeResId(R.dimen.divider) .marginResId(R.dimen.leftmargin, R.dimen.rightmargin) .build());

However, I find that the color that shows is not the same as that it should be.
Could you please help me out?

Memory Growing Issue

just install sample project. Run on an emulator. Open Memory Monitor. Scroll up and down with several times. Memory is growing. Sometimes GC start, but cannot release more memory. Always call GC.

Any idea on this issue?

Thanks

it seems VerticalDividerItemDecoration has some issue

VerticalDividerItemDecoration does not work collectly.

here is my codes:

recyclerView.addItemDecoration(new VerticalDividerItemDecoration.Builder(this)
                .margin(50, 50)
                .color(Color.BLUE)
                .size(30)
                .build());
        recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
                .margin(50, 50)
                .color(Color.YELLOW)
                .size(30)
                .build());

but the result seems incorrect!
short of vertical color draw,as the following:
default

This library is not good for GridLayoutManager. Some Suggesttion.

Problem

Method(com.yqritc.recyclerviewflexibledivider.FlexibleDividerDecoration#getGroupIndex )
calls frequently, and that method consume too much time, ui thread do too much.

google source code :

GridLayoutManager.SpanSizeLookup#getSpanGroupIndex(int, int) .
https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.SpanSizeLookup.html?hl=ja#getSpanGroupIndex(int;

        public int getSpanGroupIndex(int adapterPosition, int spanCount) {
            int span = 0;
            int group = 0;
            int positionSpanSize = getSpanSize(adapterPosition);
            for (int i = 0; i < adapterPosition; i++) {
                int size = getSpanSize(i);
                span += size;
                if (span == spanCount) {
                    span = 0;
                    group++;
                } else if (span > spanCount) {
                    // did not fit, moving to next row / column
                    span = size;
                    group++;
                }
            }
            if (span + positionSpanSize > spanCount) {
                group++;
            }
            return group;
        }

My Suggesttion

Please dont't frequently use method GridLayoutManager.SpanSizeLookup#getSpanGroupIndex(int, int) .
I do it ,and ui thread is good for show.

My Simple Code for GridLayoutManager

import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ItemDecoration;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;

public class ListSpacingDecoration extends ItemDecoration {

  private static final String TAG = ListSpacingDecoration.class.getSimpleName();

  private static final int VERTICAL = OrientationHelper.VERTICAL;

  private int orientation = -1;
  private int spanCount = -1;
  private int spacing;
  private int halfSpacing;

  public ListSpacingDecoration(int spacing) {
    super();
    this.spacing = spacing;
    this.halfSpacing = spacing / 2;
  }

  /**
   * 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator
   */
  @Override
  public void getItemOffsets(Rect outRect, final View view, RecyclerView parent, State state) {

    // super.getItemOffsets(outRect, view, parent, state);
    if (orientation == -1) {
      orientation = getOrientation(parent);
    }

    if (spanCount == -1) {
      spanCount = getTotalSpan(parent);
    }

    int childCount = parent.getLayoutManager().getItemCount();
    int childIndex = parent.getChildAdapterPosition(view);

    int itemSpanSize = getItemSpanSize(parent, childIndex);
    int spanIndex = getItemSpanIndex(parent, childIndex);

//    LogUtils.d(TAG, "getItemOffsets childCount = " + childCount + " - childIndex = " + childIndex + " : itemSpanSize = "
//        + itemSpanSize + " : spanIndex = " + spanIndex);
    /* INVALID SPAN */
    if (spanCount < 1)
      return;

    setSpacings(outRect, parent, childCount, childIndex, itemSpanSize, spanIndex);
  }

  /**
   * onDraw方法先于drawChildren
   */
  @Override
  public void onDraw(Canvas c, RecyclerView parent, State state) {
    // TODO
    super.onDraw(c, parent, state);
  }

  /**
   * onDrawOver在drawChildren之后,一般我们选择复写其中一个即可
   */
  @Override
  public void onDrawOver(Canvas c, RecyclerView parent, State state) {
    // TODO
    super.onDrawOver(c, parent, state);
  }

  protected void setSpacings(Rect outRect, RecyclerView parent, int childCount, int childIndex, int itemSpanSize,
      int spanIndex) {

    outRect.top = halfSpacing;
    outRect.bottom = halfSpacing;
    outRect.left = halfSpacing;
    outRect.right = halfSpacing;

    if (isTopEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      outRect.top = spacing;
    }

    if (isLeftEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      // outRect.left = spacing;
      outRect.left = 0;
    }

    if (isRightEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      // outRect.right = spacing;
      outRect.right = 0;
    }

    if (isBottomEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
      outRect.bottom = spacing;
    }
  }

  @SuppressWarnings("all")
  protected int getTotalSpan(RecyclerView parent) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getSpanCount();
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return ((StaggeredGridLayoutManager) mgr).getSpanCount();
    } else if (mgr instanceof LinearLayoutManager) {
      return 1;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getItemSpanSize(RecyclerView parent, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanSize(childIndex);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return 1;
    } else if (mgr instanceof LinearLayoutManager) {
      return 1;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getItemSpanIndex(RecyclerView parent, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanIndex(childIndex, spanCount);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return childIndex % spanCount;
    } else if (mgr instanceof LinearLayoutManager) {
      return 0;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getOrientation(RecyclerView parent) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof LinearLayoutManager) {
      return ((LinearLayoutManager) mgr).getOrientation();
    } else if (mgr instanceof GridLayoutManager) {
      return ((GridLayoutManager) mgr).getOrientation();
    } else if (mgr instanceof StaggeredGridLayoutManager) {
      return ((StaggeredGridLayoutManager) mgr).getOrientation();
    }

    return VERTICAL;
  }

  protected boolean isLeftEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return spanIndex == 0;

    } else {

      return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex);
    }
  }

  protected boolean isRightEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return (spanIndex + itemSpanSize) == spanCount;

    } else {

      return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex);
    }
  }

  protected boolean isTopEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex);

    } else {

      return spanIndex == 0;
    }
  }

  protected boolean isBottomEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

      return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex);

    } else {

      return (spanIndex + itemSpanSize) == spanCount;
    }
  }

  protected boolean isFirstItemEdgeValid(boolean isOneOfFirstItems, RecyclerView parent, int childIndex) {

    int totalSpanArea = 0;
    if (isOneOfFirstItems) {
      for (int i = childIndex; i >= 0; i--) {
        totalSpanArea = totalSpanArea + getItemSpanSize(parent, i);
      }
    }

    return isOneOfFirstItems && totalSpanArea <= spanCount;
  }

  protected boolean isLastItemEdgeValid(boolean isOneOfLastItems, RecyclerView parent, int childCount, int childIndex,
      int spanIndex) {

    int totalSpanRemaining = 0;
    if (isOneOfLastItems) {
      for (int i = childIndex; i < childCount; i++) {
        totalSpanRemaining = totalSpanRemaining + getItemSpanSize(parent, i);
      }
    }

    return isOneOfLastItems && (totalSpanRemaining <= spanCount - spanIndex);
  }
}

add supprot for api 9?

The lib use some API(getAlpha,getTranslationX(),getTranslationY()) don't support in api 9.

Exception thrown in DialogFragment

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicHeight()' on a null object reference
at com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration.getDividerSize(HorizontalDividerItemDecoration.java:90)
at com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration.setItemOffsets(HorizontalDividerItemDecoration.java:79)
at com.yqritc.recyclerviewflexibledivider.FlexibleDividerDecoration.getItemOffsets(FlexibleDividerDecoration.java:158)
at android.support.v7.widget.RecyclerView.getItemDecorInsetsForChild(RecyclerView.java:4489)
at android.support.v7.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:8443)

The above exception is thrown when the decoration is used with a dialog , i'll copy the style I used below:

<style name="NoFrameDialog" parent="@style/AppTheme.Dialog">
    <item name="android:windowBackground">@null</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">true</item>
</style>

I also checked it happens when using no dialog style so it's a matter of using the decoration with a recyclerview in a DialogFragment

shouldHideDivider not working

when set to true, divider is still showing

I can confirm that my adapter is implementing FlexibleDividerDecoration.VisibilityProvider and overriding shouldHideDivider. I can also confirm that shouldHideDivider is not being called

import fail?

hi,i read the readme and import like this.

repositories {
    jcenter()
}

dependencies {
    compile 'com.yqritc:recyclerview-flexibledivider:1.2.3'
}

but it always fail like this.

Error:(40, 13) Failed to resolve: com.yqritc:recyclerview-flexibledivider:1.2.3

API of `VisibilityProvider` is confusing when used in Kotlin

When using Java, the API is pretty much self explanatory:

ItemDecoration dividerDecoration = HorizontalDividerItemDecoration.Builder(this)
    .sizeResId(R.dimen.item_divider_height)
    .visibilityProvider(new VisibilityProvider() {
        @Override
        boolean shouldHideDivider(int position, RecyclerView parent) {
            // With the context of having the method name shown above, this is
            // obviously wrong.
            return true;
        }
    }
    .build();

However, because VisibilityProvider is a SAM-type, Kotlin allows you to use a trailing closure, so the name of the method isn't shown anywhere. In this case, a user's first instinct might be to return true to show the divider and false to hide it (like I did), which is backwards:

val dividerDecoration = HorizontalDividerItemDecoration.Builder(this)
    .sizeResId(R.dimen.item_divider_height)
    .visibilityProvider { position, parent ->
        // This looked right to me (visibility -> true), but is backwards.
        true
    }
    .build()

I'd suggest inverting that API so it's more Kotlin-friendly:

interface VisibilityProvider {
    boolean shouldShowDivider(int position, RecyclerView parent);
}

This issue may apply to other APIs, but I haven't run into any others yet, or had time to look.

migrate to androidx dependencies

hi, thanks in advance for your library. recently google released the new androix libraries (AKA support libraries) i will be great if you update the lib dependencies to this news libraries

missing build() in readme

hi bud, u missed calling build() in ur sample code in readme
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this))

Flashing divider when notifying multiple items changed

I'm using radio buttons in my cells in a horizontal linear layout.

I noticed that when calling notifyItemChanged on two cells at the same time, one to uncheck the radio button and one to check the radio button. That the dividers flash and glitch weirdly.

The above can be worked around by calling notifyDataSetChanged(). But the same problem occurs when calling notifyItemRemoved and notifyItemChanged at the same time which I haven't been able to work around whilst still getting the removed animation.

Thanks,
Tom

Example project
https://github.com/Sylapse/DividerSample.git

Drag&Drop on api21

I encountered a little wierd problem, with this lib.
It works perfectly with any other api version I tried, but with api 21 it "disables" the drag&drop functionality.

In ItemTouchHelper class, there is a method, called "moveIfNecessary", it always returns on the first condition, therefore onMove never get called.
I tried different support versions too.

RemoveItemDecoration not work !

RemoveItemDecoration not work !

ItemDecoration = new VerticalDividerItemDecoration.Builder(Context) .color(Color) .size(Size) .build(); recyclerView.addItemDecoration(ItemDecoration );

recyclerView.removeItemDecoration(ItemDecoration);

the divider show in left and right even if set margin

image

HorizontalDividerItemDecoration mItemDecoration = new HorizontalDividerItemDecoration.Builder(this)
                .color(ContextCompat.getColor(mContext, R.color.color_333333))
                .sizeResId(R.dimen.px_1)
                .marginResId(R.dimen.dp_16, R.dimen.dp_16)
                .build();
mRecyclerView.addItemDecoration(mItemDecoration);

Change the divider size depending not only on the position but also on the content?

Hi there,

Is there a way of changing the divider size depending not only on the position but also on the content?
In my case, my adapter extends from a CursorRecyclerAdapter and depending on the position content I set a different view type.

    @Override
    public int getItemViewType(int position) {
        if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
            String cursorUid = mCursor.getString(mCursor.getColumnIndex(ChatProvider.COL_FROM_UID));
            String previousUid = "";
            if (!mCursor.isFirst()) {
                mCursor.moveToPrevious();
                previousUid = mCursor.getString(mCursor.getColumnIndex(ChatProvider.COL_FROM_UID));
                mCursor.moveToNext();
            }

            if (cursorUid.equals(uid))
                return VIEW_TYPE_ME;
            else if (previousUid.equals(cursorUid))
                return VIEW_TYPE_OTHERS_BIS;
            else
                return VIEW_TYPE_OTHERS;

        }
        return 0;
    }

My problem is that I set the adapter to the recyclerview when the cursor is loaded inside the onLoadFinished method of the CursorLoader and the "dividerSize" method seems to get called before the cursor is loaded setting the default divider to all items.

@Override
    public int dividerSize(int position, RecyclerView parent) {
        switch (getItemViewType(position)) {
            case VIEW_TYPE_ME:
                Utils.convertDpToPixel(context.getResources().getDimension(R.dimen.divider_chat_normal), context);
                break;

            case VIEW_TYPE_OTHERS:
                Utils.convertDpToPixel(context.getResources().getDimension(R.dimen.divider_chat_normal), context);
                break;

            case VIEW_TYPE_OTHERS_BIS:
                Utils.convertDpToPixel(context.getResources().getDimension(R.dimen.divider_chat_bis), context);
                break;
        }
        return Utils.convertDpToPixel(context.getResources().getDimension(R.dimen.divider_chat_normal), context);
    }

I've tried to call addItemDecoration after the data is loaded into the cursor with no luck.

   @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        messagesChatAdapter.swapCursor(data);
        recyclerView.scrollToPosition(messagesChatAdapter.getItemCount() - 1);
        recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity())
                .sizeProvider(messagesChatAdapter)
                .color(android.R.color.transparent)
                .build());
    }

some suggest and some problem

Sorry.My English not good.
我认为应该分成 GridItemDecoration 和 LinearItemDecoration 。在每个item的周围绘制想要的divider。
这样实现起来比较简单。如果是GridLayoutManager,垂直的时候,则应该在最后一列右边 和 最后一行的下面不添加分割线。
下面是我写的一个例子,相信你能看懂

I think it should be divided into GridItemDecoration and LinearItemDecoration.Draw divider around each item instead of entire row / column.
If it's GridLayoutManager, you should not add the dividing line in the last column to the right and below the last line when vertical and vice versa.
I just like to think of it, it's easier for me to think of it, as the work that I do.
Here is an example of what I wrote, I believe you can understand

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
    if (layoutManager instanceof GridLayoutManager) {
        outRect.left = getDividerSize();
        outRect.bottom = getDividerSize();
        GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
        RecyclerView.Adapter adapter = parent.getAdapter();
        int itemCount = adapter.getItemCount();
        int position = parent.getChildAdapterPosition(view);
        int spanCount = gridLayoutManager.getSpanCount();
        GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
        int spanIndex = spanSizeLookup.getSpanIndex(position, spanCount);
        int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount);
        int lastSpanGroupIndex = spanSizeLookup.getSpanGroupIndex(itemCount - 1, spanCount);
        if (lastSpanGroupIndex == spanGroupIndex) outRect.bottom = 0;
        if (spanIndex == 0) outRect.left = 0;
        return;
    }
    Log.e(TAG, "RecyclerView must have GridLayoutManager");
}

draw divider on top of item instead of below

From the Material Design Spec

Dividers are placed along the bottom edge of the content tiles, independent of the grid.

The current implementation draws the dividers below the item:

        if (mDividerType == DividerType.DRAWABLE) {
-            bounds.top = child.getBottom() + params.topMargin + transitionY;
+            // I haven't tested the drawable implementation
+            bounds.top = child.getBottom() + params.topMargin + transitionY - dividerSize;
            bounds.bottom = bounds.top + dividerSize;
        } else {
-            bounds.top = child.getBottom() + params.topMargin + dividerSize / 2 + transitionY;
+            // this one works great
+            bounds.top = child.getBottom() + params.topMargin - dividerSize / 2 + transitionY;
            bounds.bottom = bounds.top;
        }

and this can be removed because the size does not change

    @Override
    protected void setItemOffsets(Rect outRect, int position, RecyclerView parent) {
-        outRect.set(0, 0, 0, getDividerSize(position, parent));
+        outRect.set(0, 0, 0, 0);
    }

This feature should be optional

jcenter() closed

recyclerview-flexibledivider package was hosted on jcenter() but it is closed now.

Can you put it in another repository and can the change the read.me file

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.