I have two text views side by side in my RecyclerView item. One of the views has layout_weight="1" to keep another view visible if the view is wide.
The problem is that the the view sizes are not updating when the views got recycled, so to textView id:name width is not correct when i scroll the list.
Should I somehow force the view to update the layout?
My RecyclerView item:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1" />
<LinearLayout
android:id="@+id/code_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@drawable/background_code"
android:orientation="vertical">
<TextView
android:id="@+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"/>
</LinearLayout>
</LinearLayout>
Im using RecyclerView v. 23.4.0.
Update
1. I have tried to call my RecyclerView item layout root requestLayout at the end of the adapter onBindViewHolder().
This does not any have affect, my views are not updated.
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
...
viewHolder.mLayoutRoot.requestLayout();
}
2. Maybe the problem is that the view is not yet completely drawn when I call requestLayout? So I tried to set GlobalLayoutListener and call requestLayout there. I think this helps little, but still if I have enough items, in my list not all views are updated. Owerall in my list I have around max 10 items.
ViewTreeObserver vto = viewHolder.mLayoutRoot.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
viewHolder.mLayoutRoot.requestLayout();
}
});
3. I tried to use TableLayout with shrinkColumns property to approach similar layout, but the result is same. Name text view widht is not always correctly set. Also, it looks like requestLayout has no affect at all (or am I calling it in wrong place?)
4. (28/8/2016)
I stripped down my code to bare minimum to reproduce this.
I managed to fix this using setIsRecyclable(false), like dosssik suggests, but I think it is not very good solution in terms of performance?
Here is my full list item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_marginLeft="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1" />
<TextView
android:id="@+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/background_stop_code_small"
android:ellipsize="end"
android:paddingBottom="1dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="1dp"
android:singleLine="true"
android:textSize="11sp"/>
</LinearLayout>
My adapter code:
I also tried to call invalidate(), but can not see any affect.
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Item item = getItem(position);
NormalViewHolder viewHolder = (NormalViewHolder) holder;
viewHolder.mName.setText(item.getName());
//viewHolder.mName.invalidate(); // No help
viewHolder.mCode.setText(item.getCode());
//viewHolder.mCode.invalidate(); // No help
}
Expected behaviour:
+----------------------------------------+
|[Name][Code] |
+----------------------------------------+
|[Name qwertyuiopasdfghjklzxcvb...][Code]|
+----------------------------------------+
This is how works right now if I scroll list up/down. So the layout is not updated and code is not alignet right to name. Also name is not taking always enough space.
+----------------------------------------+
|[Name][Code] |
+----------------------------------------+
|[Name qwer...] [Code] |
+----------------------------------------+
|[Name qwertyuiopa][Code] |
+----------------------------------------+
|[Name qwe] [Code] |
+----------------------------------------+
I share my solution which is not need to use
setIsRecyclable(false)
Use below custom TextView at your xml.
public class TextViewForRecyclerView extends android.support.v7.widget.AppCompatTextView {
public TextViewForRecyclerView(Context context) {
super(context);
}
public TextViewForRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public TextViewForRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
requestLayout();
}
}
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