Item Decoration adds double space - android

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;
}
}
}

Related

StaggeredLayoutManager disturbs positions of cells during adjustment in RecyclerView

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;
}
}
}

Why is the space between my RecyclerView items not the same?

I use ItemDecoration to set the space between the grid RecyclerView items, and I want the space between each item to be equal.
ItemDecoration
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) {
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
int spanSize = layoutParams.getSpanSize();
int spanIndex = layoutParams.getSpanIndex();
int totalSpanSize = gridLayoutManager.getSpanCount();
if (spanIndex == 0) {//left
outRect.left = space;
outRect.right = space / 2;
} else if (spanSize + spanIndex == totalSpanSize) {//right
outRect.right = space;
outRect.left = space / 2;
} else if (spanIndex > 0 && spanSize + spanIndex < totalSpanSize) {
outRect.left = space / 2;
outRect.right = space / 2;
}
outRect.bottom = space;
}
}
RecyclerView
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
item xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="90dp"
android:layout_height="90dp"
android:background="#ff6600"
android:orientation="vertical">
</LinearLayout>
Try this,
int spanCount;
final private Context mContext =YourActivity.this;
int value = activity.getResources().getConfiguration().orientation;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
recycler_view=(RecyclerView)findViewById(R.id.recycler_view);
recycler_view.setLayoutManager(new GridLayoutManager(mContext, 2));
if (value == Configuration.ORIENTATION_PORTRAIT) {
spanCount = 2;
}
else if (value == Configuration.ORIENTATION_LANDSCAPE) {
spanCount = 3;
}
int spacing_left = 50; // 50px
int spacing_top=10;
recycler_view.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing_left, spacing_top));
}
#Override
protected void onResume() {
if (value == Configuration.ORIENTATION_PORTRAIT) {
spanCount = 2;
}
else if (value == Configuration.ORIENTATION_LANDSCAPE) {
spanCount = 3;
}
super.onResume();
}
GridSpacingItemDecoration:
/* set spacing for grid view */
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration
{
final private int spanCount,spacing,spacing_top;
final private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing_left, int spacing_top)
{
this.spanCount = spanCount;
this.spacing = spacing_left;
this.includeEdge = true;
this.spacing_top=spacing_top;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
{
int position = parent.getChildAdapterPosition(view); // item phases_position
int column = position % spanCount; // item column
if (includeEdge)
{
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount)
{ // top edge
outRect.top = spacing_top;
}
outRect.bottom = spacing_top; // item bottom
}
else
{
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount)
{
outRect.top = spacing_top; // item top
}
}
}
}
Use GridItemDecoration:
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.DimenRes;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class GridItemDecoration extends RecyclerView.ItemDecoration {
private int mItemOffset;
public GridItemDecoration(int itemOffset) {
mItemOffset = itemOffset;
}
public GridItemDecoration(#NonNull Context context, #DimenRes int itemOffsetId) {
this(context.getResources().getDimensionPixelSize(itemOffsetId));
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(mItemOffset, mItemOffset, mItemOffset, mItemOffset);
}
}
From your Activity:
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
................
........................
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mRecyclerView.setHasFixedSize(true);
// Grid layout manager
mLayoutManager = new GridLayoutManager(mContext, 3); // spanCount = 3 for 3 columns
mRecyclerView.setLayoutManager(mLayoutManager);
// Grid item spacing
GridItemDecoration itemDecoration = new GridItemDecoration(mContext, R.dimen.grid_item_spacing); // R.dimen.grid_item_spacing is 2dp
mRecyclerView.addItemDecoration(itemDecoration);
............
......................
}
Why don't you try to remove the code for the custom spacing, and use the grid parameters android:horizontalSpacing and android:verticalSpacing?
Add android:scaleType="fitXY" inside your item xml which will scale the image using FILL so that all items occupy same area.

recycler view gridmanager layout column spacing does not give equal space in all side

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;

Equal spacing between items inside a RecyclerView that is using a StaggeredGridLayoutManager?

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?

RecyclerView item decoration

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?

Categories

Resources