3

I have a RecyclerView in which items are a LinearLayout with several TextViews as childs. Depending on some rules (this is decided in onBindViewHolder), the TextViews might be hidden away (visibility GONE) or shown.

My problem is that if I have for example 3 items (A, B and C) in the RecyclerView with the same number of visible TextViews and A is on top of the list, B in the middle and C at the bottom, if for example B has to show more TextViews than before, during a brief period of time this item (B) will overlap with C since it has grown in size and has to accommodate the new visible TextViews which were previously with visibility GONE.

Visual representation of the problem:

Desired situation

enter image description here

Current and undesired situation

enter image description here

After a bit the RecyclerViewaccommodates the item correctly.

How can I avoid this from happening?

EDIT:

In one of the comments is suggested that I might have to animate and transforms the views myself. Is that necessary or is there another way of doing it? If so, how can I animate and transform the views?

EDIT 2:

Tried this answer: Animating items, but the problems persists. There's a visible delay until the RecyclerView updates.

EDIT 3:

I am using this class (RecyclerViewCursorAdapter) as base for the adapter that populates the RecyclerView. Aditionally, I am doing this in onResume

@Override
public void onResume()
{
    super.onResume();

    if(getActivity().getSupportLoaderManager().getLoader(R.id.myLoaderId) == null)
    {
        getActivity().getSupportLoaderManager().initLoader(R.id.myLoaderId, null, this);
    }
    else
    {
        getActivity().getSupportLoaderManager().restartLoader(R.id.myLoaderId, null, this);
    }
}
OneEyeQuestion
  • 742
  • 7
  • 22
  • Try making the `TextViews` `INVISIBLE` instead of `GONE`. – sonictt1 Apr 11 '16 at 00:43
  • Can you post your code showing what's going on? If the data changes you should be able to simply call recyclerView.getAdapter().notifyDataSetChanged(); and it should redraw the recyclerView correctly. – LNI Apr 11 '16 at 00:57
  • @LNI I am doing that, but as stated, the problem arises during a brief period of time (I guess while the `RecyclerView` updates), then it is rendered correctly. – OneEyeQuestion Apr 11 '16 at 01:12
  • @sonictt1 That would leave 'holes' in the item, and since some items will have some `TextViews` active and others don't it will have an undesired appearance for me. – OneEyeQuestion Apr 11 '16 at 01:15
  • You question is unclear. Perhaps you could post an image for better illustration of what you're trying to describe. – Elye Apr 11 '16 at 02:20
  • If you can't reserve space in the item for the text that might appear, you'll have to transform and animate your views by hand as RecyclerView only redraws your view after it has exited and re-entered the screen. – sonictt1 Apr 11 '16 at 19:35
  • @sonictt1 Ok, could be. But why is it that it worked with `ListView` but not with `RecyclerView`? – OneEyeQuestion Apr 12 '16 at 00:28
  • @Elye Updated post with pictures. – OneEyeQuestion Apr 12 '16 at 00:28

5 Answers5

1

The key was using the setIsRecyclable() method of RecyclerView.ViewHolder class. Set this property true as enter link description here

taranjeetsapra
  • 524
  • 7
  • 19
0

Your problem is that: in your xml (item view), you declare textView with default attribute:

android:visibility="gone"

when check condition:

if (condition) {
    textView.setVisibility(View.VISIBLE);
}

Instead of that, you should do like this:

if (condition) {
    textView.setVisibility(View.VISIBLE);
} else {
    textView.setVisibility(View.GONE);
}
Norutan
  • 1,480
  • 2
  • 14
  • 27
  • I am doing what you suggest. The problem is that when the visibility is changed to `VISIBLE`, the `RecyclerView` shows for a brief period of time the item with new height but overlapping the item below. – OneEyeQuestion Apr 11 '16 at 23:41
  • My code is exactly as yours if you remove the data binding and all that stuff – OneEyeQuestion Apr 12 '16 at 23:47
0

if its height becomes 0, it won't be visible :). I assume your root layout does have some min height (or exact height) that makes it still take space even though it is GONE.

0

If you also need to add smooth animation effect,try this one.

By default put visibility == gone.

    @Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
    super.onBindViewHolder(holder, position);

    holderG.layoutReply.setVisibility(View.GONE);
}

And set visibility something like :

 holder.button.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View view)
                {
                        if (holderG.layoutReply.getVisibility() == View.VISIBLE) {                   
                            notifyItemChanged(holderG.getAdapterPosition());
                        }
                        else {holderG.layoutReply.setVisibility(View.VISIBLE);
                        }
                    }
                }
            });

and in your inflator layout set

android:animateLayoutChanges="true"

for parent layout.

Note-- in case of visibility==VISIBLE, animate layout changes works fine and smooth but in case of visibility==GONE items overlap each other thats why I am using notifyItemChanged to change back the visibility of view.

Gagan
  • 745
  • 10
  • 31
0

Use notifyItemChanged(int position) function provided by the RecyclerView adpater to notify that an item got changed.

Skaldebane
  • 95
  • 2
  • 11