I have just started using ItemDecoration
. I am trying to achieve a divider in the middle of a two-column RecyclerView
managed by StaggeredGridLayoutManager
.
Here's my ItemDecoration
code :
public class LobbyItemDecoration extends RecyclerView.ItemDecoration {
private int margin;
private Drawable drawable;
public LobbyItemDecoration(int margin, Drawable drawable){
this.margin = margin;
this.drawable = drawable;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams)view .getLayoutParams();
int spanIndex = lp.getSpanIndex();
if(position >= 0){
if (position < ((LobiAdapter)parent.getAdapter()).getmDataset().size()){
if(spanIndex == 1){
outRect.left = margin;
((LobiAdapter)parent.getAdapter()).getmDataset().get(position).left = false;
} else {
outRect.right = margin;
((LobiAdapter)parent.getAdapter()).getmDataset().get(position).left = true;
}
outRect.bottom = margin;
}
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (drawable == null) { super.onDrawOver(c, parent, state);return; }
if(parent.getItemAnimator() != null && parent.getItemAnimator().isRunning()) {
return;
}
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i=1; i < childCount; i++) {
final View child = parent.getChildAt(i);
StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams)child .getLayoutParams();
int spanIndex = lp.getSpanIndex();
int size = drawable.getIntrinsicWidth();
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int ty = (int)(child.getTranslationY() + 0.5f);
final int tx = (int)(child.getTranslationX() + 0.5f);
final int leftIndex1 = child.getLeft() - (margin * 4 / 3) - tx;
final int rightIndex1 = child.getLeft() - (margin * 2 / 3) - tx;
final int leftIndex0 = child.getRight() + (margin * 2 / 3) + tx;
final int rightIndex0 = child.getRight() + (margin * 4 / 3) + tx;
if(spanIndex == 1){
// drawable.setBounds(100, top, 5, bottom);
drawable.setBounds(leftIndex1, top, rightIndex1, bottom);
drawable.draw(c);
} else {
drawable.setBounds(leftIndex0, top, rightIndex0, bottom);
drawable.draw(c);
// drawable.setBounds(5, top, 100, bottom);
}
}
}
}
Problem is as title said, whenever I load new item or scroll, the decoration is sometimes gone or misplaced. By gone I mean, literally gone, it's not there anymore until I scroll down or up to recycle the View
.
And by misplaced I mean, when I scroll down, and the loading ViewHolder
is in the left column, the divider "sticks" to the left column. If the loading ViewHolder
is in the right column, it is normal.
Just in case : I use a ViewHolder
to be a progress indicator by adding one null item and check it in getItemViewType()
then remove it later after finishing the load from server.
This is how I add :
for (PostModel postModel :
dataSet) {
this.mDataset.add(postModel);
notifyItemInserted(mDataset.size() - 1);
}
StaggeredGridLayoutManager is buggy. For me this helped:
diffResult.dispatchUpdatesTo(this);
recyclerView.postDelayed(() -> {
layoutManager.invalidateSpanAssignments(); // to fix first item in second column issue
recyclerView.invalidateItemDecorations(); // to fix wrong spacing
}, 50);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With