2016-08-18 2 views
6

У меня есть два текстовых вида рядом со мной в элементе RecyclerView. В одном из представлений layout_weight = "1", чтобы увидеть другое вид, если вид широко.RecyclerView item layout_weight, размеры не обновляются

Проблема заключается в том, что размеры вида не обновляются, когда просмотры переработаны, поэтому для textView id: ширина имени неверна, когда я просматриваю список.

Должен ли я каким-то образом заставить просмотр обновить макет?

Мой RecyclerView пункт:.

<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 использованием RecyclerView V 23.4.0.

Update

1. Я попытался назвать мой 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(); 
    } 
}); 

3. Я пытался использовать 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> 

Мой адаптер Код:

Я также попытался вызвать Invalidate(), но не может видеть никакого влияния.

@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]| 
+----------------------------------------+ 

Это как работает прямо сейчас, если я перечисляю список вверх/вниз. Поэтому макет не обновляется, а код не выравнивается, чтобы его можно было назвать. Также имя не занимает всегда достаточно места.

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

Не могли бы вы разместить фото/видео о проблеме? А также вы могли бы опубликовать полный код реализации метода 'onBindViewHolder'? – rom4ek

+1

Снимок экрана, пожалуйста? –

+0

Почему второе текстовое изображение в линейном режиме? позаботьтесь о том, чтобы разработать для меня логику здесь? – Elltz

ответ

3

Этот XML работает для меня без использования setIsRecyclable(false);
В некоторых андроид версии (например, KitKat) код: android:ellipsize="end" работает только с android:singleLine="true", поэтому добавьте в первый TextView «@ + ид/имя», и он будет работы !

<?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 The будет повторно использовать ViewHolder объекты так, макеты тех, будут завышены один раз, а затем повторно использовать в течение жизни списка. Попробуйте позвонить requestLayout на свой корень LinearLayout.

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

У меня была очень проблема simillar с recyclerView. Иногда это работает неправильно, когда предметы перерабатываются, к сожалению.

Мне помогли отключить пригодную для повторного использования.

 setIsRecyclable(false); 

вы можете сделать это в constuctor ViewHolder как это:

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

Я разделяю мое решение, которое не нужно использовать

setIsRecyclable(false) 

Использование ниже пользовательских TextView в вашем 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(); 
    } 
} 
Смежные вопросы