Skip to content

Commit

Permalink
tidy up code to use group index for providers if layoutManager is Gri…
Browse files Browse the repository at this point in the history
…dLayoutManager
  • Loading branch information
yqritc committed Jan 18, 2016
1 parent 4b8c8a6 commit c08cfc4
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 90 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
If you want to customize divider depending on the position, implement the following interfaces.

### List of provider
The following providers can be implemented and controllable for each divider drawn between cells.
The following providers can be implemented and controllable for each divider drawn between cells.
Please refer to ComplexAdapter class in the [sample](/sample/src/main/java/com/yqritc/recyclerviewflexibledivider/sample) for the usage of providers in detail.

- ColorProvider
Provide color for divider
Expand All @@ -87,9 +88,10 @@ Enables you to control the visibility of dividers.
Enables you to specify left and right margin of divider.

- MarginProvider for vertical divider (horizontal list)
Enables you to specify top and bottom margin of divider.
Enables you to specify top and bottom margin of divider.

Please refer to ComplexAdapter class in the [sample](/sample/src/main/java/com/yqritc/recyclerviewflexibledivider/sample) for the usage of providers in detail.
**For GridLayoutManager**, the position parameter of above providers is group index of items.
So, control your divider based on [group index](http://developer.android.com/intl/ja/reference/android/support/v7/widget/GridLayoutManager.SpanSizeLookup.html#getSpanGroupIndex(int, int)) instead of the position of items.

### Optional

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import android.support.annotation.DrawableRes;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

Expand Down Expand Up @@ -84,24 +83,27 @@ public int dividerSize(int position, RecyclerView parent) {

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int lastChildPosition = -1;
int itemCount = parent.getAdapter().getItemCount();
int lastDividerOffset = getLastDividerOffset(parent);

int childCount = mShowLastDivider ? parent.getChildCount() : parent.getChildCount() - lastDividerOffset;
for (int i = 0; i < childCount; i++) {
int validChildCount = parent.getChildCount();
int lastChildPosition = -1;
for (int i = 0; i < validChildCount; i++) {
View child = parent.getChildAt(i);
int childPosition = parent.getChildAdapterPosition(child);

if (childPosition < lastChildPosition) {
// Avoid remaining divider when animation starts
continue;
}
boolean dividerWasAlreadyDrawn = wasDividerAlreadyDrawnForPosition(parent,childPosition,lastChildPosition);

lastChildPosition = childPosition;

if (dividerWasAlreadyDrawn) {
// no need to draw divider again as it was drawn already by previous column
if (!mShowLastDivider && childPosition >= itemCount - lastDividerOffset) {
// Don't draw divider for last line if mShowLastDivider = false
continue;
}

if (wasDividerAlreadyDrawn(childPosition, parent)) {
// No need to draw divider again as it was drawn already by previous column
continue;
}

Expand All @@ -110,85 +112,108 @@ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
continue;
}

if (mVisibilityProvider.shouldHideDivider(childPosition, parent)) {
int groupIndex = getGroupIndex(childPosition, parent);
if (mVisibilityProvider.shouldHideDivider(groupIndex, parent)) {
continue;
}



Rect bounds = getDividerBound(childPosition, parent, child);
Rect bounds = getDividerBound(groupIndex, parent, child);
switch (mDividerType) {
case DRAWABLE:
Drawable drawable = mDrawableProvider.drawableProvider(childPosition, parent);
Drawable drawable = mDrawableProvider.drawableProvider(groupIndex, parent);
drawable.setBounds(bounds);
drawable.draw(c);
break;
case PAINT:
mPaint = mPaintProvider.dividerPaint(childPosition, parent);
mPaint = mPaintProvider.dividerPaint(groupIndex, parent);
c.drawLine(bounds.left, bounds.top, bounds.right, bounds.bottom, mPaint);
break;
case COLOR:
mPaint.setColor(mColorProvider.dividerColor(childPosition, parent));
mPaint.setStrokeWidth(mSizeProvider.dividerSize(childPosition, parent));
mPaint.setColor(mColorProvider.dividerColor(groupIndex, parent));
mPaint.setStrokeWidth(mSizeProvider.dividerSize(groupIndex, parent));
c.drawLine(bounds.left, bounds.top, bounds.right, bounds.bottom, mPaint);
break;
}
}
}

/**
* Determines whether divider was already drawn for the row the item is in,
* effectively only makes sense for a grid
*
* @param parent RecyclerView
* @param position current view position to draw divider
* @param lastChildPosition previous view position
* @return true if the divider can be skipped as it is in the same row as the previous one.
*/
private boolean wasDividerAlreadyDrawnForPosition(RecyclerView parent, int position, int lastChildPosition) {
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
int spanCount = gridLayoutManager.getSpanCount();
GridLayoutManager.SpanSizeLookup spanSizeLockup = gridLayoutManager.getSpanSizeLookup();
if (spanSizeLockup.getSpanGroupIndex(position,spanCount) == spanSizeLockup.getSpanGroupIndex(lastChildPosition,spanCount) && lastChildPosition != -1) {
return true;
}
@Override
public void getItemOffsets(Rect rect, View v, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(v);
int itemCount = parent.getAdapter().getItemCount();
int lastDividerOffset = getLastDividerOffset(parent);
if (!mShowLastDivider && position >= itemCount - lastDividerOffset) {
// Don't set item offset for last line if mShowLastDivider = false
return;
}
return false;

int groupIndex = getGroupIndex(position, parent);
setItemOffsets(rect, groupIndex, parent);
}

/**
* In the case mShowLastDivider = false,
* Returns offset for how many views we don't have to draw a divider for,
* for LinearLayoutManager it is as simple as not drawing the last child divider,
* but for a GridLayoutManager it needs to take the span count for the last items into account
* until we use the span count configured for the grid.
*
* @param parent RecyclerView
* @return offset for how many views we don't have to draw a divider or 1 if its a LinearLayoutManager
* @param parent RecyclerView
* @return offset for how many views we don't have to draw a divider or 1 if its a
* LinearLayoutManager
*/
private int getLastDividerOffset(RecyclerView parent) {
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
int spanCount = gridLayoutManager.getSpanCount();
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
int spanCount = layoutManager.getSpanCount();
int itemCount = parent.getAdapter().getItemCount();
int lastRowItems = itemCount % spanCount;
int lastItemIndex =itemCount - 1;
GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
int lastRowSpanSize = 0;
for (int i=lastItemIndex;i>0;i--) {
lastRowSpanSize += spanSizeLookup.getSpanSize(i);
if (lastRowSpanSize >= spanCount || i == lastItemIndex - lastRowItems) {
for (int i = itemCount - 1; i >= 0; i--) {
if (spanSizeLookup.getSpanIndex(i, spanCount) == 0) {
return itemCount - i;
}
}
}

return 1;
}

@Override
public void getItemOffsets(Rect rect, View v, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(v);
setItemOffsets(rect, position, parent);
/**
* Determines whether divider was already drawn for the row the item is in,
* effectively only makes sense for a grid
*
* @param position current view position to draw divider
* @param parent RecyclerView
* @return true if the divider can be skipped as it is in the same row as the previous one.
*/
private boolean wasDividerAlreadyDrawn(int position, RecyclerView parent) {
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
int spanCount = layoutManager.getSpanCount();
return spanSizeLookup.getSpanIndex(position, spanCount) > 0;
}

return false;
}

/**
* Returns a group index for GridLayoutManager.
* for LinearLayoutManager, always returns position.
*
* @param position current view position to draw divider
* @param parent RecyclerView
* @return group index of items
*/
private int getGroupIndex(int position, RecyclerView parent) {
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
int spanCount = layoutManager.getSpanCount();
return spanSizeLookup.getSpanGroupIndex(position, spanCount);
}

return position;
}

protected abstract Rect getDividerBound(int position, RecyclerView parent, View child);
Expand All @@ -203,7 +228,7 @@ public interface VisibilityProvider {
/**
* Returns true if divider should be hidden.
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return True if the divider at position should be hidden
*/
Expand All @@ -218,7 +243,7 @@ public interface PaintProvider {
/**
* Returns {@link android.graphics.Paint} for divider
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return Paint instance
*/
Expand All @@ -233,7 +258,7 @@ public interface ColorProvider {
/**
* Returns {@link android.graphics.Color} value of divider
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return Color value
*/
Expand All @@ -248,7 +273,7 @@ public interface DrawableProvider {
/**
* Returns drawable instance for divider
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return Drawable instance
*/
Expand All @@ -264,7 +289,7 @@ public interface SizeProvider {
* Returns size value of divider.
* Height for horizontal divider, width for vertical divider
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return Size of divider
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public interface MarginProvider {
/**
* Returns left margin of divider.
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return left margin
*/
Expand All @@ -77,7 +77,7 @@ public interface MarginProvider {
/**
* Returns right margin of divider.
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return right margin
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public interface MarginProvider {
/**
* Returns top margin of divider.
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return top margin
*/
Expand All @@ -77,7 +77,7 @@ public interface MarginProvider {
/**
* Returns bottom margin of divider.
*
* @param position Divider position
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
* @return bottom margin
*/
Expand Down
6 changes: 3 additions & 3 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
<activity
android:name=".PaintActivity"
android:label="@string/menu_paint"/>
<activity
android:name=".SimpleGridActivity"
android:label="@string/menu_simple_grid"/>
<activity
android:name=".DrawableActivity"
android:label="@string/menu_drawable"/>
<activity
android:name=".ComplexActivity"
android:label="@string/menu_complex"/>
<activity
android:name=".SimpleGridActivity"
android:label="@string/menu_simple_grid"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_simple:
SimpleActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
case R.id.action_paint:
PaintActivity.startActivity(this);
return true;
Expand All @@ -71,6 +68,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_complex:
ComplexActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_simple:
SimpleActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
case R.id.action_paint:
PaintActivity.startActivity(this);
return true;
Expand All @@ -63,6 +60,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_complex:
ComplexActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_simple:
SimpleActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
case R.id.action_paint:
PaintActivity.startActivity(this);
return true;
Expand All @@ -79,6 +76,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_complex:
ComplexActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_simple:
SimpleActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
case R.id.action_paint:
PaintActivity.startActivity(this);
return true;
Expand All @@ -60,6 +57,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_complex:
ComplexActivity.startActivity(this);
return true;
case R.id.action_simple_grid:
SimpleGridActivity.startActivity(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand Down
Loading

0 comments on commit c08cfc4

Please sign in to comment.