RecyclerView different itemDecoration for different items
By : Danny Brammel
Date : March 29 2020, 07:55 AM
|
Items are not the same width when using RecyclerView GridLayoutManager to make column spacing by ItemDecoration
By : sandeep
Date : March 29 2020, 07:55 AM
fixed the issue. Will look into that further I found the reason of the problem by myself. The offset that made in ItemDecoration is regarded as a part of item's dimensions(width and height)! Let's take a look at the sample code and screen capture in the question above. The width of the screen capture is 480 pixels, and here is 3 columns, each item's width is 480/3 = 160 pixels. In SpacingDecoration, I add a left offset (20 pixels) on the first and second column, so the content's width of first and second column item is 160-20=140, then I add both left and right offset on the 3rd column item, so the content's width of 3rd column item is 160-20-20=120. code :
spacing = 20
columnCount = 3
rowWidth = 480
itemWidth = rowWidth / columnCount
itemOccupiedSpacing = (spacing * (columnCount + 1)) / columnCount = spacing + spacing * (1/columnCount)
itemContentWidth = itemWidth - itemOccupiedSpacing
firstItemLeftOffset = spacing = spacing * (3/columnCount)
firstItemRightOffset = itemOccupiedSpacing - spacing = spacing * (1/columnCount)
secondItemLeftOffset = spacing - firstRightOffset = spacing * (2/columnCount)
secondItemRightOffset = itemOccupiedSpacing - secondLeftOffset = spacing * (2/columnCount)
thirdItemLeftOffset = itemOccupiedSpacing - secondLeftOffset = spacing * (1/columnCount)
thirdItemRightOffset = spacing = spacing * (3/columnCount)
itemLeftOffset = spacing * ((columnCount - colunmnIndex) / columnCount)
itemRightOffset = spacing * ((colunmnIndex + 1) / columnCount)
public class SpacingDecoration extends ItemDecoration {
private int mHorizontalSpacing = 0;
private int mVerticalSpacing = 0;
private boolean mIncludeEdge = false;
public SpacingDecoration(int hSpacing, int vSpacing, boolean includeEdge) {
mHorizontalSpacing = hSpacing;
mVerticalSpacing = vSpacing;
mIncludeEdge = includeEdge;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// Only handle the vertical situation
int position = parent.getChildAdapterPosition(view);
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
int spanCount = layoutManager.getSpanCount();
int column = position % spanCount;
getGridItemOffsets(outRect, position, column, spanCount);
} else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager();
int spanCount = layoutManager.getSpanCount();
StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
int column = lp.getSpanIndex();
getGridItemOffsets(outRect, position, column, spanCount);
} else if (parent.getLayoutManager() instanceof LinearLayoutManager) {
outRect.left = mHorizontalSpacing;
outRect.right = mHorizontalSpacing;
if (mIncludeEdge) {
if (position == 0) {
outRect.top = mVerticalSpacing;
}
outRect.bottom = mVerticalSpacing;
} else {
if (position > 0) {
outRect.top = mVerticalSpacing;
}
}
}
}
private void getGridItemOffsets(Rect outRect, int position, int column, int spanCount) {
if (mIncludeEdge) {
outRect.left = mHorizontalSpacing * (spanCount - column) / spanCount;
outRect.right = mHorizontalSpacing * (column + 1) / spanCount;
if (position < spanCount) {
outRect.top = mVerticalSpacing;
}
outRect.bottom = mVerticalSpacing;
} else {
outRect.left = mHorizontalSpacing * column / spanCount;
outRect.right = mHorizontalSpacing * (spanCount - 1 - column) / spanCount;
if (position >= spanCount) {
outRect.top = mVerticalSpacing;
}
}
}
}
|
ItemDecoration Before LayoutManager?
By : Walmo Augusto Walmo
Date : March 29 2020, 07:55 AM
will be helpful for those in need Interesting question, but I don't believe it matters if you set the layout manager before or after the item decoration. Both calls result in a request for layout. I am going to guess that you are adding the decoration to the RecyclerView more than one time. Since decorations compound, you will see a greater gap with the decoration added two times (or more times) instead of just once.
|
How to draw a view in an ItemDecoration?
By : droogstore
Date : March 29 2020, 07:55 AM
I wish this help you Figured it out (Oops my bounty) In order for a View to be created correctly, it needs 3 steps: code :
private fun initHeader(parent: RecyclerView?) {
if (header == null) {
val view = parent?.context?.inflate(R.layout.decoration, parent, false)
val bitmap = Bitmap.createBitmap(parent?.width?:0, 40.dp(), Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val widthSpec = View.MeasureSpec.makeMeasureSpec(parent?.width ?: 0, View.MeasureSpec.EXACTLY)
val heightSpec = View.MeasureSpec.makeMeasureSpec(40.dp(), View.MeasureSpec.EXACTLY)
view?.measure(widthSpec, heightSpec)
view?.layout(0, 0, parent.width, 40.dp())
view?.draw(canvas)
header = bitmap
}
}
|
How to set ItemDecoration only for certain ViewType?
By : kahseong
Date : December 23 2020, 07:01 PM
With these it helps Problem My mistake consists of the conviction to use ItemDecoration in order to set custom dividers for different ViewType. I have developed a clear belief that such a custom dividers should do only ItemDecoration. code :
<LinearLayout ...>
<TextView ... />
<!-- This -->
<View style="@style/DividerStyle" />
</LinearLayout>
<style name="DividerStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/dividerHeight</item>
<item name="android:background">@android:color/black</item>
</style>
|