-
-
Save alexfu/0f464fc3742f134ccd1e to your computer and use it in GitHub Desktop.
/* | |
* Copyright (C) 2014 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
public class DividerItemDecoration extends RecyclerView.ItemDecoration { | |
private static final int[] ATTRS = new int[]{ | |
android.R.attr.listDivider | |
}; | |
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; | |
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; | |
private Drawable mDivider; | |
private int mOrientation; | |
public DividerItemDecoration(Context context, int orientation) { | |
final TypedArray a = context.obtainStyledAttributes(ATTRS); | |
mDivider = a.getDrawable(0); | |
a.recycle(); | |
setOrientation(orientation); | |
} | |
public void setOrientation(int orientation) { | |
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { | |
throw new IllegalArgumentException("invalid orientation"); | |
} | |
mOrientation = orientation; | |
} | |
@Override | |
public void onDraw(Canvas c, RecyclerView parent) { | |
if (mOrientation == VERTICAL_LIST) { | |
drawVertical(c, parent); | |
} else { | |
drawHorizontal(c, parent); | |
} | |
} | |
public void drawVertical(Canvas c, RecyclerView parent) { | |
final int left = parent.getPaddingLeft(); | |
final int right = parent.getWidth() - parent.getPaddingRight(); | |
final int childCount = parent.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = parent.getChildAt(i); | |
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child | |
.getLayoutParams(); | |
final int top = child.getBottom() + params.bottomMargin; | |
final int bottom = top + mDivider.getIntrinsicHeight(); | |
mDivider.setBounds(left, top, right, bottom); | |
mDivider.draw(c); | |
} | |
} | |
public void drawHorizontal(Canvas c, RecyclerView parent) { | |
final int top = parent.getPaddingTop(); | |
final int bottom = parent.getHeight() - parent.getPaddingBottom(); | |
final int childCount = parent.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = parent.getChildAt(i); | |
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child | |
.getLayoutParams(); | |
final int left = child.getRight() + params.rightMargin; | |
final int right = left + mDivider.getIntrinsicHeight(); | |
mDivider.setBounds(left, top, right, bottom); | |
mDivider.draw(c); | |
} | |
} | |
@Override | |
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { | |
if (mOrientation == VERTICAL_LIST) { | |
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); | |
} else { | |
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); | |
} | |
} | |
} |
That params has been deprecated and replaced with better params. Check my gist
What about onDrawOver(), is that a useful method compared to onDraw()?
onDrawOver() will draw over the items in the list, onDraw() will draw under the items.
Simple RecyclerView Divider
https://gist.github.com/polbins/e37206fbc444207c0e92
@btdrucke yep!
SpacesItemDecoration
https://gist.github.com/yrom/3b4bcbc2370ca2290434
Hi! Consider using
RecyclerView.LayoutManager manager = parent.getLayoutManager();
final int left = manager.getDecoratedLeft(child);
to better support multiple ItemDecorations. For example if you add DividerItemDecoration and another ItemDecoration for spacing between items, dividers will be drawn at the end of each item instead of right between them because you are not consider offsets from other decorations.
drawVertical should look like this for example:
public void drawVertical(Canvas c, RecyclerView parent)
{
RecyclerView.LayoutManager manager = parent.getLayoutManager();
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final int top = manager.getDecoratedBottom(child);
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
Thank you for this gist!
Grate work, simple and do what its should ,Thanks .
Based on your work i added a grid support , but i don't know what is the proper way to submit the change to the original git. Please check it out and marge it with the original for other to enjoy.
https://gist.github.com/AviBenHamo/638e48ca2a4525431656
P.s I did try this tutorial without any luck, Its written for a repository and not a Git!.
https://help.github.com/articles/creating-a-pull-request/
Thanks,
Avi.
At line 58 possible to be used childCount-1 to avoid drawing divider after last item in list
I wonder if it is a good idea to use Paint instead of bothering creating a drawable resource?
Any performance difference?
public DividerItemDecoration(Context context, int colorResId, int dividerWidthDimenResId) {
mPaint = new Paint();
mPaint.setColor(context.getResources().getColor(colorResId));
mPaint.setStrokeWidth((int) context.getResources().getDimension(dividerWidthDimenResId));
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int startX = parent.getPaddingLeft();
int stopX = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int y = child.getBottom() + params.bottomMargin;
c.drawLine(startX, y, stopX, y, mPaint);
}
}
possible bug at line 79, it should be
final int right = left + mDivider.getIntrinsicWidth();
mDivider = a.getDrawable(0);
Returns null for 5.1.1
Also adding:
mDivider = a.getDrawable(0);
returns a null drawable.
Also adding:
Line 79:
final int right = left + mDivider.getIntrinsicWidth();
Thanks for this code. I am using it to set the divider in a PreferenceFragmentCompat. For a PreferenceFragmentCompat I had to make a change so not to display a divider line under the last element. To do this, I changed drawVertical() and drawHorizontal():
from:
for (int i = 0; i < childCount; i++) {
to:
for (int i = 0; i < childCount-1; i++) {
Thanks.
You should not be looping over 0 to childCount (with or without the -1). You should loop from findFirstVisibleItemPosition() to findLastVisibleItemPosition(), checking them first for NO_POSITION. The last item check would then be whether the position is the last item from the adapter.
Didn't work for android 5.0 +
how i can increase divider width and height???????
Why is onDraw and getItemOffsets deprecated now?