2

I'm using RecyclerView along with StaggeredGridLayoutManager for showing items with slightly different appearance. in items I use AspectRatioImageView by JakeWharton (link) to maintain the imageView sizes before the image actually downloaded and shown by Picasso. RV (RecyclerView) is populated by server data in infinite scroll pattern.

The problem is (as shown in included pictures), when scolling, some gaps appear on top and bottom of RV (in picture and sometimes items moves between the columns! (taking screenshot is hard :D)

Edit 2: A really important thing I forgot, is that I use the same layout for all of the items but regarding to adapter items some part of the layouts change their visibility to Gone or vice versa.

My question: Why RV behave like this? Am I doing something wrong? Is this normal in RV?

empty area on top left of RecyclerView

The code is large and I don't know which part is useful to put here. If you can narrow down the cause I will put some code here.


EDIT: Code parts related to problem

xml:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_texture"
    android:padding="@dimen/padding_lvlhalf"
    android:scrollbarStyle="outsideOverlay"/>

initializing view:

@Bind(R.id.recycler_view) RecyclerView mRecyclerView;
.
.
.
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(columnCount, direction));
mRecyclerView.setAdapter(
    new RecyclerViewAdapter<>(ctx, new ViewFiller<Post, DashboardPostViewHolder>() {
        @Override
        public void fill(Post post, DashboardPostViewHolder holder) {
            holder.fill(post);
        }

        @Override
        public DashboardPostViewHolder getViewHolder(View view) {
            return new DashboardPostViewHolder(view, receiverName);
        }

        @Override
        public int getLayoutID() {
            return R.layout.post_dashboard;
        }

    });)

My custom Adapter:

    public RecyclerViewAdapter(Context context, ViewFiller filler) {
    super();
    this.filler = filler;
    mLayoutInflater = LayoutInflater.from(context);
    items = new ArrayList<>();
}

@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent,
                                         int viewType) {
    View v = mLayoutInflater.inflate(filler.getLayoutID(), parent, false);
    return filler.getViewHolder(v);
}

@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
    filler.fill(getItem(position), holder);
}

@Override
public int getItemCount() {
    return items.size();
}

@Override
public long getItemId(int position) {
    return position;
}

public T getItem(int position){
    return items.get(position);
}

public void addItem(int position, T item){
    items.add(position, item);
    notifyItemInserted(position);
}

public void addItem(T item){
    items.add(item);
    notifyItemInserted(items.size() - 1);
}

public void addItems(List<T> data){
    int oldSize = items.size();
    items.addAll(data);
    notifyItemRangeInserted(oldSize, data.size());
}

public void addItemsToListHead(List<T> data){
    items.addAll(0, data);
    notifyItemRangeInserted(0, data.size());
}

public void resetData(List<T> data) {
    this.items = data;
    notifyDataSetChanged();
}

public void removeItem(int position){
    items.remove(position);
    notifyItemRemoved(position);
}

public void clear(){
    this.items.clear();
    notifyDataSetChanged();
}

public List<T> getItems(){
    return items;
}

ViewFiller interface

public interface ViewFiller<D, VH extends BaseViewHolder>{
    void fill(D data, VH holder);

    VH getViewHolder(View view);

    @LayoutRes int getLayoutID();
}

Edit 2 (Cont.): My items xml and how I fill them..

    <android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="@dimen/margin_lvlhalf"
    app:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/post"
        android:background="@color/poinila_background">


        <TextView
            android:layout_gravity="right"
            android:text="@string/test_title"
            android:layout_margin="@dimen/margin_lvl1"
            style="@style/match_wrap.large_text.centered_right"
            android:id="@+id/post_title"
            android:visibility="gone"/>

        <!--Post Image-->
        <com.shaya.poinila.android.presentation.view.AspectRatioImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitXY"
            android:contentDescription="@string/post_content_description"
            android:id="@+id/post_image"
            android:visibility="gone"
            app:aspectRatioEnabled="true"
            app:dominantMeasurement="width"
            />

        <!--Content-->
        <TextView
            android:id="@+id/post_content"
            style="@style/match_wrap.medium_text.three_line.end_ellipsize"
            android:layout_margin="@dimen/margin_lvl1"/>
        <!--android:text="@string/test_long"-->

        <include layout="@layout/horizontal_line"
            />

        <!--Post Author-->
        <include android:id="@+id/post_author"
            layout="@layout/circle_image_title_subtitle_reverse"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/margin_lvl1"/>

        <include layout="@layout/horizontal_line"
            />

        <!--Post Stats (favs, comments, etc) -->
        <include android:id="@+id/post_stats"
            layout="@layout/stats"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/margin_lvlhalf"
            android:layout_marginBottom="@dimen/margin_lvlhalf"/>

        <include layout="@layout/horizontal_line"/>

        <!--Post Collection Info-->
        <include layout="@layout/rounded_image_title_subtitle_reverse"
            android:id="@+id/post_collection"/>

    </LinearLayout>
</android.support.v7.widget.CardView>

PostViewHolder class

public class PostViewHolder extends RecyclerView.ViewHolder
    public void fill(Post post) {
        if (post.type == PostType.IMAGE) {
            postImage.setVisibility(View.VISIBLE);
            postName.setVisibility(TextUtils.isEmpty(post.name) ? View.VISIBLE : View.GONE);
            /*if (TextUtils.isEmpty(post.summary))
                postContent.setVisibility(View.GONE);*/
        }else{ //post.type == PostType.TEXT
            postImage.setVisibility(View.GONE);
            postName.setVisibility(View.VISIBLE);
            postContent.setVisibility(View.VISIBLE);
        }
        // contetnt
        if (TextUtils.isEmpty(post.summary) && !TextUtils.isEmpty(post.contentUrl)) {
            DataRepository.getInstance().getPostContent(post.contentUrl, postContent);
        }
        else{
            setText(postContent, post.summary);
        }
    .
    .
    .
    }   
}

Sorry for the long post!

Alireza Farahani
  • 2,238
  • 3
  • 30
  • 54
  • Hello.. Did you solve this issue? I have the same problem.. Thank you. – Gennadii Saprykin Mar 08 '16 at 19:52
  • @GennadiiSaprykin : Not completely! But keep in mind RV use limited number of child views and reuse them for different item (objects in RV adapter), so in `onBindView` you must initialize (visiblity, values, size, state, etc) child view's parts and sub views completely from beginning. sorry for bad English, Hope I'm clear enough! – Alireza Farahani Mar 09 '16 at 15:41
  • 1
    Yeah, I think I initialize everything in `onBindViewHolder` although I still had gaps. This hack worked for me though: http://stackoverflow.com/questions/33126960/android-staggeredgridlayoutmanager-offset-bug Looks ugly but removes all the gaps. – Gennadii Saprykin Mar 09 '16 at 15:47
  • This might be the issue, check below link [http://stackoverflow.com/questions/35817610/large-gap-forms-between-recyclerview-items-when-scrolling-down](http://stackoverflow.com/questions/35817610/large-gap-forms-between-recyclerview-items-when-scrolling-down) – Himanshu Jain Sep 28 '16 at 04:15

2 Answers2

0
  1. You probably have margins in your root ViewGroup of item.
  2. manager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
dtx12
  • 4,438
  • 1
  • 16
  • 12
  • Thank for you reply. I wasn't aware of that! Do you know what's the reason behind of gaps being made? If they are inevitable in SGV, isn't the HANDLING_NONE a bad approach? – Alireza Farahani Sep 09 '15 at 13:58
  • I did what you said and the only difference made is that RV doesn't fill that gaps anymore! Gaps still apearing... – Alireza Farahani Sep 09 '15 at 14:09
  • Add your layout to question. – dtx12 Sep 09 '15 at 14:14
  • I edited the question. Tell me if anything is confusing or extra code is needed. – Alireza Farahani Sep 09 '15 at 16:24
  • Hey, you forgot to add item layout. – dtx12 Sep 09 '15 at 16:39
  • I added the items xml layout and how the viewholder views are filled with adapter items. – Alireza Farahani Sep 10 '15 at 07:49
  • According with your updated question, I'd like to ask you. Do you restore visibility of all elements even if they were hidden? At least it's not so clear on your images attached to question, because on image from the right side your items looks different. While I see, that in this case my answer is not useful for you at all, it could be probably just a caching issue. – dtx12 Sep 10 '15 at 08:39
0

Do this ,spacing between the grid items stay same

private boolean flagDecoration = false;
if(!flagDecoration)
{
    ItemOffsetDecoration itemDecoration = new ItemOffsetDecoration(getContext(),(R.dimen.spacing));
    recyclerView.addItemDecoration(itemDecoration);
    flagDecoration = true;
}
legoscia
  • 39,593
  • 22
  • 116
  • 167
prav
  • 11
  • 2