Recycler View - 一个视图打开另一个视图

时间:2016-04-22 17:06:16

标签: android layout android-recyclerview

我对回收站视图有疑问。我有几个可以扩展的卡片视图。单击其中一个并向下滚动后,另一个打开,但当我向后滚动时,应该打开的那个被关闭。这是不一致和非常令人困惑的,我甚至不知道如何描述它。谢谢你的帮助。

Recycler查看项目布局:

<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/card_margin_bottom"
android:layout_marginLeft="@dimen/card_margin_sides"
android:layout_marginRight="@dimen/card_margin_sides"
android:layout_marginTop="@dimen/card_margin_top">

<LinearLayout
    style="@style/Widget.CardContent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <TextView
        android:id="@+id/headerText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:textSize="@dimen/adapter_card_view_title_text_size"/>


    <TextView
        android:id="@+id/expandText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textSize="@dimen/adapter_card_view_expand_text_size"
        android:visibility="gone"/>

</LinearLayout>

适配器:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private String[] headerText;
private String[] techniqueText;

public static class ViewHolder extends RecyclerView.ViewHolder {
    public TextView headerText;
    public TextView expandText;
    public CardView mCardView;

    public ViewHolder(CardView v) {
        super(v);
        mCardView = v;
        headerText = (TextView) v.findViewById(R.id.headerText);
        expandText = (TextView) v.findViewById(R.id.expandText);
    }
}

public RecyclerViewAdapter(String[] firstParam, String[] secondParam) {
    headerText = firstParam;
    techniqueText = secondParam;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_view_layout, parent, false);

    ViewHolder vh = new ViewHolder((CardView) v,parent.getContext());
    return vh;
}

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    holder.headerText.setText(headerText[position]);
    holder.expandText.setText(techniqueText[position]);
    holder.mCardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (holder.expandText.getVisibility() == View.GONE) {
                holder.expandText.setVisibility(View.VISIBLE);
            }
            else if (holder.expandText.getVisibility() == View.VISIBLE){
                holder.expandText.setVisibility(View.GONE);
            }
        }
    });
}

@Override
public int getItemCount() {
    return headerText.length;
}

}

Recycler View设置

mRecyclerView = (RecyclerView)   v.findViewById(R.id.recycler_x);
    mRecyclerView.setHasFixedSize(false);
    mLayoutManager = new LinearLayoutManager(this.getContext());
    mRecyclerView.setLayoutManager(mLayoutManager);
    mAdapter = new RecyclerViewAdapter(firstParam,secondParam);
    mRecyclerView.setAdapter(mAdapter);

2 个答案:

答案 0 :(得分:1)

您的观点正在被回收。如果您打开一个视图并向下滚动,那么该布局(处于打开状态)将被回收用于新条目,该条目也将显示为打开状态。您需要在回收时重置每个视图的状态,如下所示:

private final Set<Integer> mOpenIndices = new HashSet<>();

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    holder.headerText.setText(headerText[position]);
    holder.expandText.setText(techniqueText[position]);

    if (mOpenIndices.contains(position)) {
        holder.expandText.setVisibility(View.VISIBLE);
    } else {
        holder.expandText.setVisibility(View.GONE);
    }

    holder.mCardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (holder.expandText.getVisibility() == View.GONE) {
                holder.expandText.setVisibility(View.VISIBLE);
                mOpenIndices.add(position);
            }
            else if (holder.expandText.getVisibility() == View.VISIBLE){
                holder.expandText.setVisibility(View.GONE);
                mOpenIndices.remove(position);
            }
        }
    });
}

现在您只需要跟踪视图状态(打开/关闭)。例如,您可以使用包含开放视图索引的一组整数,或者您喜欢的其他一些解决方案。

答案 1 :(得分:1)

RecyclerView的概念是它只为可见项创建了几个视图,当它们超出屏幕限制时会被回收。这在内存和性能方面对大型列表(数百或数千个项目)产生巨大影响。

您遇到的情况是View被回收并因此失去其状态。您需要明确地存储状态并在onBindViewHolder中恢复它。类似的东西:

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    holder.headerText.setText(headerText[position]);
    holder.expandText.setText(techniqueText[position]);
    holder.expandText.setVisibility(expanded[position] ? View.VISIBLE: View.GONE);
    holder.mCardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            expanded[position] = !expanded[position]
            holder.expandText.setVisibility(expanded[position] ? View.VISIBLE: View.GONE);
        }
    });
}

这意味着您需要一个名为expanded的额外ArrayList,其大小足以保持您的状态。