2016-08-18 64 views
6

我在我的RecyclerView项目中并排显示两个文本视图。其中一个视图具有layout_weight =“1”,以便在视图很宽的情况下保持另一个视图可见。RecyclerView项目layout_weight,尺寸不更新

问题是视图大小没有更新时,视图被回收,所以textView id:名称宽度不正确,当我滚动列表。

我应该以某种方式强制视图更新布局?

我RecyclerView项目:使用RecyclerView v

<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> 

林23.4.0。

我试图打电话给我RecyclerView项目布局根requestLayout在适配器onBindViewHolder结束更新()。

这没有任何影响,我的意见没有更新。

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
    ... 
    viewHolder.mLayoutRoot.requestLayout(); 
} 

2.也许问题是,鉴于尚未完全当我打电话requestLayout画?所以我试图设置GlobalLayoutListener并在那里调用requestLayout。我认为这有所帮助,但如果我有足够的项目,在我的列表中不是所有视图都会更新。 Owerall在我的列表中有大约10个项目。

ViewTreeObserver vto = viewHolder.mLayoutRoot.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
     viewHolder.mLayoutRoot.requestLayout(); 
    } 
}); 

我试图用TableLayout与shrinkColumns财产接近类似的布局,但结果是一样的。名称文本视图widht并不总是正确设置。此外,它看起来像requestLayout已经没有在所有影响(或我称它在错误的地方?)

4(28/8/2016)

我剥了下来我的代码,以最低限度,以重现这一点。

我设法使用setIsRecyclable(false)来解决这个问题,就像dosssik所建议的那样,但是我认为它在性能方面不是很好的解决方案?

这是我的完整列表项:

<?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> 

我的适配器代码:

我也试图调用无效(),但看不到任何影响。

@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 
} 

预期的行为:

+----------------------------------------+ 
|[Name][Code]       | 
+----------------------------------------+ 
|[Name qwertyuiopasdfghjklzxcvb...][Code]| 
+----------------------------------------+ 

这是现在如果我滚动列表向上/向下是如何工作的。所以布局不会更新,代码也不是alignet的名称。另外名字并没有占用足够的空间。

+----------------------------------------+ 
|[Name][Code]       | 
+----------------------------------------+ 
|[Name qwer...]    [Code] | 
+----------------------------------------+ 
|[Name qwertyuiopa][Code]    | 
+----------------------------------------+ 
|[Name qwe]  [Code]    | 
+----------------------------------------+ 
+1

你可以发布一些问题的照片/视频?你也可以发布你的'onBindViewHolder'方法实现的完整代码吗? – rom4ek

+1

截图请问? –

+0

为什么是线性布局中的第二个textview?谨慎地为我阐述这里的逻辑? – Elltz

回答

3

这个XML为我工作,而无需使用setIsRecyclable(false);
在某些Android版本(如奇巧)的代码:android:ellipsize="end"只有android:singleLine="true"的作品,所以这增加了第一TextView的“@ + ID /名称”,它会工作!

<?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:singleLine="true" 
    android:maxLines="1" 
    /> 
    <TextView 
    android:id="@+id/code" 
    android:layout_weight="0" 
    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> 


结果:

enter image description here

1

RecyclerView将重用ViewHolder对象,以便这些的布局将被一旦膨胀,然后通过列表的寿命重复使用。请尝试拨打您的根LinearLayout上的requestLayout

Usage of forceLayout(), requestLayout() and invalidate()

+0

我试图将viewHolder.mLayoutRoot.requestLayout()调用添加到我的适配器onBindViewHolder的末尾,但仍然无法正确更新我的布局。如果文本名称被更改,LinearLayout code_container widht不会更新。 – devha

1

您需要作废两个TextView意见,并确保你正在做它,你设定新的价值给他们后:

@Override 
public void onBindViewHolder(ItemHolder holder, int position) 
{ 
    ... 

    holder.nameTextView.invalidate(); 
    holder.codeTextView.invalidate(); 
} 

作为替代方案,如果你不”不要介意代码视图对齐到右侧,您可以将LinearLayout替换为RelativeLayout,并在名称视图和代码容器之间设置适当的约束:

<TextView 
    android:id="@+id/name" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_marginRight="8dp" 
    android:layout_centerVertical="true" 
    android:layout_alignParentStart="true" 
    android:layout_alignParentLeft="true" 
    android:layout_toLeftOf="@+id/code_container" 
    android:layout_toStartOf="@+id/code_container" 
    android:ellipsize="end" 
    android:maxLines="1" /> 

<LinearLayout 
    android:id="@+id/code_container" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_centerVertical="true" 
    android:layout_alignParentEnd="true" 
    android:layout_alignParentRight="true" 
    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> 

0

我曾在使用RecyclerView聊天样活性布局刷新的问题:我叫从onBindViewHolder的方法,以适应任何聊天消息的利润率,下面的代码片段: .. RecyclerView.LayoutParams lp =(RecyclerView.LayoutParams)this.mItemView.getLayoutParams(); lp.setMargins(0,0,50,0);

-1

嗯,我没有得到确切的问题,你面对的是...但我可以在你的代码中看到的一个问题是你的代码是重量,你正在用错误的方式使用重量。如果您在一个小部件中使用重量,则重量无效,至少您必须使用两个小部件才能在它们之间给予适当的权重,并在其父项中使用权重总和才能正常工作。例如见下面你的修改代码: -

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginLeft="16dp" 
    android:gravity="center_vertical" 
    android:orientation="horizontal" 
    android:weightSum="3"> 

    <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:text="qwertyuioopasdfsd" /> 

    <LinearLayout 
     android:id="@+id/code_container" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_vertical" 
     android:layout_weight="2" 
     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" /> 

    </LinearLayout> 

</LinearLayout> 
0

我已经与recyclerView非常simillar问题。 有时它不正常,当物品回收,不幸。

对我帮助关闭可回收。

 setIsRecyclable(false); 

你可以做到这一点在ViewHolder的constuctor这样的:

class Holder extends RecyclerView.ViewHolder { 

    public Holder(View itemView) { 
     super(itemView); 
     setIsRecyclable(false); 

    } 
} 

当然,这不是真棒解决方案,但它是唯一的解决方案,帮助我。

希望它能帮助你。

+0

谢谢!到目前为止,这只是解决方案的作用,但我希望有更好的方法来刷新我所需要的观点? – devha

0

试试这个我没有使用编辑器,但它会自动正确的,如果使用XML的任何问题

<?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="match_parent" //i changed this 
android:layout_height="150dp" 
android:layout_marginLeft="16dp" 
android:weightsum="1"//added this 
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:singleLine="true" />//added this 

<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> 

上述将工作

如果你仍然坚持更新的布局,总是知道你需要的更新是测量,那么你需要拨打View.invalidate()以及View.requestLayout()

+0

我无法将root linearLayout宽度设置为match_parent,因为我的代码视图始终位于屏幕的右侧。代码需要在名称视图之后。 – devha

1

我终于得到了正确的答案。由于我的测试,你可以只添加两行,你的方法onBindViewHolder,如下:

@Override 
public void onBindViewHolder(ItemHolder holder, int position) 
{ 
    holder.mName.setSingleLine(false); //first line 
    holder.mName.setText("name"); 
    holder.mCode.setText(""); 
    holder.mName.setSingleLine(true); //second line 
} 

希望它可以帮助你。

1

你应该增加重量内用线性布局还那么这将是

<TextView 
    android:id="@+id/name" 
    android:layout_width="0dp" 
    android:layout_height="wrap_content" 
    android:layout_marginRight="8dp" 
    android:layout_weight="2" 
    android:ellipsize="end" 
    android:maxLines="1" /> 

<LinearLayout 
    android:id="@+id/code_container" 
    android:layout_width="0dp" 
    android:layout_weight="1" 
    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> 

尝试这会为你

0
As it seems code is of constant length, you can use following UI deisgn; 
<RelativeLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_marginLeft="16dp" 
    android:gravity="center_vertical"> 

    <TextView 
     android:id="@+id/name" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:align_parentLeft="true" 
     android:layout_toLeftOf="@+id/code" 
     android:layout_marginRight="8dp" 
     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_code" 
      android:gravity="center" 
      android:align_ParentRight="true" 
      android:ellipsize="end" 
      android:paddingBottom="1dp" 
      android:paddingLeft="7dp" 
      android:paddingRight="7dp" 
      android:paddingTop="1dp" 
      android:singleLine="true"/> 

</RelativeLayout> 
+0

其实代码可以是可变长度的,我原来的问题对此没有什么误导。 – devha

0

尝试使用这个,我有同样的问题开展工作,我解决它使用此:

@Override 
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View rootView = LayoutInflater.from(context).inflate(R.layout.review_data, null, false); 
     RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 
     rootView.setLayoutParams(lp); 
     return new ViewHolder(rootView); 
    } 

像上面一样在onCreateViewHolder中设置布局参数。

0

只是其中之一的设置权重是错误的,因为当code长时,name将会消失。 我不知道什么是你想实现的,但即使是一个简单的ListView和一个简单的布局像下面的项目,他们将永远不会消失,我认为他们更好看:

<?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:gravity="left" 
android:layout_marginLeft="16dp" 
android:orientation="horizontal"> 

<TextView 
    android:id="@+id/name" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_weight=".5" 
    android:layout_marginRight="8dp" 
    android:ellipsize="end" 
    android:text="dfsdd45te5sf" 
    android:maxLines="1" /> 

<TextView 
    android:id="@+id/code" 
    android:layout_weight=".5" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:background="@android:color/holo_green_dark" 
    android:ellipsize="end" 
    android:paddingBottom="1dp" 
    android:paddingLeft="7dp" 
    android:paddingRight="7dp" 
    android:paddingTop="1dp" 
    android:layout_marginRight="1dp" 
    android:text="ertertete5tte5tte5e5te5t" 
    android:singleLine="true" 
    android:textSize="12sp"/> 
</LinearLayout> 
0

我分享我的解决方案,这需要使用下面的自定义的TextView

setIsRecyclable(false) 

使用你的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(); 
    } 
}