Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView layout changed and values truncated upon scrolling

I've dealt with RecyclerView a few times, but this time I made the height/width of items of the RecyclerView to wrap_content. What happened with this implementation is that whenever I scroll the RecyclerView, the layout and values of the items in it get messed up as well. E.g. the layout was too small to fit the values of the item, hence the values getting truncated, when I scroll up and down on the RecyclerView.

Recyclerview hiccup!

I understand that scrolling a RecyclerView will inevitably recycle the views, reusing the first displayed layout when the activity is created. And please do correct me if I'm wrong about this logic.

I hope to get some solutions or workarounds to this problem because I would really love to have the RecyclerView item's layout to nicely conform the value. Just like the Messenger app where the card view is nicely sized to its content. Can I achieve this without fixing the sizes of the view?

Thanks a lot!

Edit: I'll post the code here, if this might give you a better overview of my problem.

RecyclerView Adapter

public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {

private static final String TAG = ChatAdapter.class.getSimpleName();

private Context context;
ArrayList<Conversation> conversations;
Conversation conversation;
private static final int TYPE_SENDER = 1;
private static final int TYPE_RECIPIENT = 2;

// Pass in the context and users array into the constructor
public ChatAdapter(Context context, ArrayList<Conversation> conversations) {
    super();
    this.context = context;
    this.conversations = conversations;
}

@Override
public int getItemViewType(int position) {
    conversation = conversations.get(position);
    if (conversation.getIsSender().equals("1")) {
        return TYPE_SENDER;
    } else {
        return TYPE_RECIPIENT;
    }
}

// Create a new ViewHolder to contain our text and image
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
    ViewHolder viewHolder;
    LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

    switch (position) {
        case TYPE_SENDER:
            View v1 = inflater.inflate(R.layout.chat_item_sender, viewGroup, false);
            viewHolder = new ViewHolder(v1);
            break;
        case TYPE_RECIPIENT:
            View v2 = inflater.inflate(R.layout.chat_item_recipient, viewGroup, false);
            viewHolder = new ViewHolder(v2);
            break;
        default:
            View v = inflater.inflate(R.layout.chat_item_sender, viewGroup, false);
            viewHolder = new ViewHolder(v);
    }
    return viewHolder;
}

// Display our text and image at the specified position in the list
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    conversation = conversations.get(position);

    // Feed the message, duration, must put in IF statement or data recycled will be buggy!
    if (!conversation.getMessage().isEmpty()) {
        viewHolder.message.setText(conversation.getMessage());
    } else {
        viewHolder.message.setTypeface(null, Typeface.ITALIC);
        viewHolder.message.setText("Message not retrievable at the moment!");
    }

    if (!conversation.getDate().toString().isEmpty()) {
        viewHolder.duration.setText(DateUtils.getRelativeDateTimeString(context,
                conversation.getDate().getTime(),
                DateUtils.SECOND_IN_MILLIS,
                DateUtils.DAY_IN_MILLIS, 0));
    } else {
        viewHolder.duration.setVisibility(View.GONE);
    }
}

// Get the number of items in the adapter
@Override
public int getItemCount() {
    return conversations.size();
}

public class ViewHolder extends RecyclerView.ViewHolder {

    public TextView message, duration;

    public ViewHolder(View itemView) {
        super(itemView);

        message = (TextView) itemView.findViewById(R.id.chat_message);
        duration = (TextView) itemView.findViewById(R.id.chat_duration);
    }

}
}

chat_item_sender.xml

Note: Same as chat_item_recipient.xml, which are the items for the RecyclerView; chat_item_sender.xml is the orange view on the right

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginTop="10dp"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1">

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_marginRight="20dp"
        android:layout_weight="5"
        android:gravity="right|center_vertical">

        <android.support.v7.widget.CardView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            card_view:cardBackgroundColor="@color/primary"
            card_view:cardCornerRadius="10dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:contentPadding="10dp">

            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/chat_message"
                    android:layout_width="fill_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:textColor="@color/white"
                    android:text="@string/shorter_test" />

                <TextView
                    android:id="@+id/chat_duration"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="bottom|right"
                    android:text="Duration"
                    android:textColor="@color/secondary_white_text"
                    android:textSize="12sp" />

            </LinearLayout>

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

    </LinearLayout>

</LinearLayout>

like image 331
Reynolds R. G. G. Avatar asked Feb 13 '16 04:02

Reynolds R. G. G.


1 Answers

Take the view that is causing the problem, for your case its the TextView that contains text of a chat. Make requestLayout method call of the view on binding.

viewHolder.message.requestLayout();

But remember to call this on your textView not on the layout with wrap_content above it!

like image 77
Mussa Avatar answered Oct 01 '22 11:10

Mussa