I have a RecyclerView with a GridLayoutManager.
I set a custom ItemDecoration:
public class ListDetailsItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public ListDetailsItemDecoration(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int itemPosition = parent.getChildPosition(view);
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
if(itemPosition == 0 || itemPosition == 1) {
outRect.top = space;
}
if(itemPosition % 2 == 0) {
outRect.right = space / 2;
} else {
outRect.left = space / 2;
}
}
}
It works great until I need to remove anyone.
notifyItemRemoved(position);
The grid isn't resized.
Any ideas?
Related
I am trying to implement this kind of RecyclerView by using GridLayoutMangaer as its layout. However, I am facing the issue while implementing the item spacing for each item in the grid.
My aim is to have an implementation like image below
Please click on this link to preview image
Any solutions for this kind of implementation would be appreciated
public class GridRec extends RecyclerView.ItemDecoration {
private int space;
public GridRec(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
if (parent.getChildLayoutPosition(view) == 0) {
outRect.top = space;
} else {
outRect.top = 0;
}
}
}
int my_space = getResources().getDimension(R.dimen.test);
myRecyclerView.addItemDecoration(new GridRec(my_space));
-----------------------------------------------------------
public class abc extends RecyclerView.ItemDecoration {
private int myPadding_psx;
private int myPadding_edge_psx;
public abc(Activity activity) {
final Resources resources = activity.getResources();
myPadding_psx = (int) resources.getDimension(R.dimen.myDefault);
myPadding_edge_psx = (int) resources.getDimension(R.dimen.mYDefaultEdge);
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
final int itemPosition = parent.getChildAdapterPosition(view);
if (itemPosition == RecyclerView.NO_POSITION) {
return;
}
int orientation = getOrientation(parent);
final int itemCount = state.getItemCount();
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
//Horizontal
if (orientation == LinearLayoutManager.HORIZONTAL) {
left = myPadding_psx;
right =myPadding_psx;
if (itemPosition == 0) {
left += myPadding_edge_psx;
}
else if (itemCount > 0 && itemPosition == itemCount - 1) {
right += myPadding_edge_psx;
}
}
//Vertical
else {
top = myPadding_psx;
bottom = myPadding_psx;
if (itemPosition == 0) {
top += myPadding_edge_psx;
}
else if (itemCount > 0 && itemPosition == itemCount - 1) {
bottom += myPadding_edge_psx;
}
}
if (!isReverseLayout(parent)) {
outRect.set(left, top, right, bottom);
} else {
outRect.set(right, bottom, left, top);
}
}
private boolean isReverseLayout(RecyclerView parent) {
if (parent.getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
return layoutManager.getReverseLayout();
} else {
throw new IllegalStateException("Error.");
}
}
private int getOrientation(RecyclerView parent) {
if (parent.getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
return layoutManager.getOrientation();
} else {
throw new IllegalStateException("Error.");
}
}
}
StaggeredLayoutManager sometimes makes cells position disordered during scroll when trying to adjust them. I've a HeaderView and NormalViews in my RecyclerView. Following is the setup code:
int spacing = (int) getResources().getDimension(R.dimen.post_item_spacing);
mBindings.rvPosts.addItemDecoration(new PostsEqualGapItemDecoration(AppConstants.POSTS_SPAN_COUNT, spacing));
mPostsLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
mBindings.rvPosts.setLayoutManager(mPostsLayoutManager);
mProfileAdapter.setRecyclerView(mBindings.rvPosts);
mBindings.rvPosts.setAdapter(mAdapter);
mBindings.rvPosts.setNestedScrollingEnabled(false);
ItemDecoration class:
public class PostsEqualGapItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
public PostsEqualGapItemDecoration(int spanCount, int spacing) {
this.spanCount = spanCount;
this.spacing = spacing;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
if (layoutParams.isFullSpan()) {
outRect.set(0, 0, 0, 0);
} else {
int spanIndex = layoutParams.getSpanIndex();
int layoutPosition = layoutParams.getViewLayoutPosition();
int itemCount = parent.getAdapter().getItemCount();
boolean leftEdge = spanIndex == 0;
boolean rightEdge = spanIndex == (spanCount - 1);
boolean topEdge = spanIndex < spanCount;
boolean bottomEdge = layoutPosition >= (itemCount - spanCount);
int halfSpacing = spacing / 2;
/**
* Updated values to keep cells width same and spacing from left and right
* most item to be double than gap between items themselves.
*/
outRect.set(
leftEdge ? spacing * 2 : rightEdge ? 0 : spacing,
topEdge ? spacing : halfSpacing,
rightEdge ? spacing * 2 : leftEdge ? 0 : spacing,
bottomEdge ? spacing : 0
);
}
}
}
Screenshot:
You have to write custom item decoration for that case to your child item views
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
// Add top margin only for the first item to avoid double space between items
if (parent.getChildLayoutPosition(view) == 0) {
outRect.top = space;
} else {
outRect.top = 0;
}
}
}
I have a recycler view where I want to add a space between the cells.
Using the code below works however, In the middle The space is doubled.
How can I space them and avoid the double space at the middle?
public class ItemDecorationAlbumColumns extends RecyclerView.ItemDecoration {
private int space;
public ItemDecorationAlbumColumns(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
// Add top margin only for the first item to avoid double space between items
if(parent.getChildAdapterPosition(view) == 0) {
outRect.top = space;
}
}
}
Calling:
recyclerView.addItemDecoration(new ItemDecorationAlbumColumns(50));
Solved using the code below:
public class ItemDecorationAlbumColumns extends RecyclerView.ItemDecoration {
private int space;
public ItemDecorationAlbumColumns(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if(parent.getChildAdapterPosition(view) % 2 == 0) {
outRect.right = space;
outRect.bottom = space;
outRect.left = space/2;
} else {
outRect.left = space;
outRect.right = space/2;
outRect.bottom = space;
}
if(parent.getChildAdapterPosition(view) == 0) {
outRect.top = space;
outRect.left = space;
}
}
}
enter image description here//I have recycler view as follows in xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/toolbar" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/grid_recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:background="#f8f9fb"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/list_recycle_view"
android:visibility="invisible"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
//in my onprepareGridView method i have done following
private void prepareGridRecycleView() {
gridRecyclerView.setHasFixedSize(true);
SpaceItemDecoration itemDecoration = new SpaceItemDecoration(10);
gridRecyclerView.setClipToPadding(false);
gridRecyclerView.addItemDecoration(itemDecoration);
adapter = new ShopPageGridViewAdapter(ShopPageContent.this, new ShopPageHeaderGridInterface() {
#Override
public void onClick(boolean isClicked) {
gridRecyclerView.setVisibility(View.INVISIBLE);
listRecycleView.setVisibility(View.VISIBLE);
}
}, new ShopPageHeaderListInterface() {
#Override
public void onClick(boolean isClicked) {
}
}, new CartCoordivateInfoHolder() {
#Override
public void setViewCoordinate(ImageView view, int x, int y) {
view.setVisibility(View.VISIBLE);
view.bringToFront();
view.invalidate();
int pos[] = new int[2];
cart.getLocationOnScreen(pos);
Log.e("x", String.valueOf(pos[0]));
Log.e("y", String.valueOf(pos[1]));
TranslateAnimation anim = new TranslateAnimation(0, pos[0] - x, 0, pos[1] - y);
anim.setDuration(5000);
anim.setFillAfter(true);
view.startAnimation(anim);
}
});
final GridLayoutManager manager = new GridLayoutManager(this, 2);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return adapter.isPositionHeader(position) ? manager.getSpanCount() : 1;
}
});
gridRecyclerView.setAdapter(adapter);
gridRecyclerView.setLayoutManager(manager);
}
//and the item decorator class looks like the following
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpaceItemDecoration(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
if (position == 0) {
outRect.left = 0;
outRect.right = 0;
outRect.bottom = 0;
outRect.top = 0;
return;
}
if (parent.getChildAdapterPosition(view) == 1 || parent.getChildAdapterPosition(view) == 2) {
outRect.top = 0;
outRect.left =(space);
outRect.right = space;
outRect.bottom = space;
return;
}
outRect.left = space;[enter image description here][1]
outRect.right = space;
outRect.bottom = space;
outRect.top = space;
}
}
//The problem i am facing is space at the left side and right side different. Left side space are smaller than the right side space.
//image link
Try to:
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpaceItemDecoration(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
outRect.top = space;
if(position%2==0){
outRect.left = 0;
}
}
}
This code is not tested;
Currently trying to do that by using this class:
public class EqualItemSpacingDecoration extends RecyclerView.ItemDecoration {
private int space;
public EqualItemSpacingDecoration(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.bottom = space;
if (parent.getChildLayoutPosition(view) < 2)
outRect.top = space;
if (parent.getChildLayoutPosition(view) % 2 == 0) {
outRect.left = space;
outRect.right = space / 2;
} else {
outRect.left = space / 2;
outRect.right = space;
}
}
}
And use it with this code:
recycler.addItemDecoration(new EqualItemSpacingDecoration(12));
But the spacing isn't equal. The third item in the screenshot below has an incorrect spacing :
How will I be able to fix this issue?