【问题标题】:RecyclerView layout changed and values truncated upon scrollingRecyclerView 布局更改并且值在滚动时被截断
【发布时间】:2016-02-13 04:20:56
【问题描述】:

我已经处理过几次RecyclerView,但这次我将itemsheight/widthRecyclerView 变成了wrap_content。这个实现发生的事情是,每当我滚动RecyclerView 时,其中项目的布局和值也会变得混乱。例如。布局太小,无法容纳项目的值,因此当我在 RecyclerView 上上下滚动时,值会被截断。

我知道滚动RecyclerView 将不可避免地回收视图,在创建活动时重复使用第一个显示的布局。如果我对这个逻辑有误,请纠正我。

我希望得到一些解决方案或变通办法来解决这个问题,因为我真的很想拥有RecyclerView 项目的布局以很好地符合价值。就像 Messenger 应用程序一样,卡片视图的大小适合其内容。我可以在不固定视图大小的情况下实现这一点吗?

非常感谢!

编辑: 我将在此处发布代码,如果这可以让您更好地了解我的问题。

RecyclerView 适配器

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

注意:和chat_item_recipient.xml一样,都是RecyclerView的item; chat_item_sender.xml 是右侧的橙色视图

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

【问题讨论】:

  • 如果是垂直滚动的RecyclerView,为什么不把item的宽度设置成match_parent呢?
  • @DougStevenson 如果值很短,那会不会让视图用完布局中的所有水平空间并留下大量空白空间?
  • 我明白了。在没有看到您的代码的情况下,我只能建议在适配器的 getView() 方法中调用 View.requestLayout() 。可能是 wrap_content 标志仅在布局期间应用,并且如果回收的视图没有理由自行布局再次(谁知道回收是否会触发),然后它就保持在当前大小。
  • 您的视图布局让我感到困惑。您有一个包含单个水平线性布局的垂直线性布局。外部布局没有任何帮助。然后那个水平线性布局包含一个空的线性布局 - 那有什么作用?然后那里有另一个线性布局,其中只包含一个 CardView 子级。这一切似乎都是多余的。线性布局旨在包含多个子级。您可能需要考虑对其进行简化,并使其在进入回收站视图之前运行良好。
  • 这对我很有用,可能对你有帮助:stackoverflow.com/questions/30082000/…

标签: android android-layout adapter android-recyclerview


【解决方案1】:

查看导致问题的视图,对于您的情况,它是包含聊天文本的 TextView。在绑定时调用视图的requestLayout方法。

viewHolder.message.requestLayout();

但记得在你的 textView 上调用它,而不是在上面有 wrap_content 的布局上调用它!

【讨论】:

  • 该死的对!花费整个改变一切我认为这是一个约束布局问题所以将其更改为相对和...但是请记住在您的 textView 上调用它而不是在上面带有 wrap_content 的布局上调用它!
【解决方案2】:

不要在你的布局文件中使用android:layout_weight,管理你的布局没有重量。问题将得到解决。

【讨论】:

    【解决方案3】:

    问题在于将 textview 与父视图嵌套。虽然回收器视图在绑定期间优化内存使用,但它基本上从池中提取未更改的视图并重新使用它。由于父视图没有被更改,而只是 textview 被更改,因此它使用了池中宽度错误的视图之一。

    所以解决方案是不要将文本视图包装在父视图中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-09
      • 1970-01-01
      • 2015-09-03
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 2021-07-09
      相关资源
      最近更新 更多