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
.
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>
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With