Android RecyclerView:为什么列表中的第一项已被选中?

时间:2016-08-07 20:59:29

标签: android android-recyclerview android-adapter

我有一个带有默认背景白色的CardViews的RecyclerView列表。我设置了OnLongClickListener以选择CardView并加载DialogFragment以确认删除项目(CardView)并将背景颜色更改为红色。

一切正常,除非列表中创建的第一个CardView已经显示红色背景,即使用户没有OnLongClicked CardView。此后,即使用户尚未OnLongClicked CardView,添加的最新CardView也始终显示红色背景。我在这里缺少什么?

background_selector.xml:

...
<!-- Normal state. -->
<item android:drawable="@color/list_contact_item_default"
    android:state_pressed="false"
    android:state_selected="false"  />

<!-- Selected state. -->

<item android:drawable="@color/item_selected"
    android:state_pressed="false"
    android:state_selected="true" />

</selector>

list_contact_tem.xml:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/singlecard_view1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    card_view:cardCornerRadius="6dp"
    card_view:cardElevation="4dp"  >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/background_selector">
    ...

适配器文件:

public class ContactListAdapter extends RecyclerView.Adapter<ContactListAdapter.ContactHolder>{
    ...
    private int selectedPos;

    @Override
    public ContactHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);

    final ContactHolder contactHolder = new ContactHolder(view);

    // Attach a LongClick listener to the items's (row) view.
    contactHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View view) {
            // Save the new selected position.
            selectedPos = contactHolder.getAdapterPosition(); // get the item position.
            if (selectedPos != RecyclerView.NO_POSITION) {
                if (recyclerItemClickListener != null) {
                    recyclerItemClickListener.onItemLongClick(selectedPos, contactHolder.itemView);
                        // Temporarily save the last selected position
                        int lastSelectedPosition = selectedPos;
                        // Update the previous selected row
                        notifyItemChanged(lastSelectedPosition);
                        notifyItemChanged(selectedPos);
                }
            }
            return true;
        }
    });

    return contactHolder;
    }

    @Override
    public void onBindViewHolder(ContactHolder holder, int position) {
        final Contact contact = contactList.get(position);

        if(position == selectedPos) {
            holder.itemView.setSelected(true);
        } else {
            holder.itemView.setSelected(false);
        }

    holder.thumb.setImageBitmap(letterBitmap);
    holder.name.setText(contact.getName());
    holder.phone.setText(contact.getPhone());
}             

1 个答案:

答案 0 :(得分:0)

您需要声明一个外部数组来跟踪所选的项目。让我们有一个与列表大小相同的数组。

private int[] selectedArray = new int[yourList.size()];

// Now initialize the Array with all zeros
for(int i=0; i<selectedArray.length; i++)
    selectedArray[i] = 0;

现在在适配器内部,当单击某个项目时,将{1}设置在selectedArray中的正确位置。这样,我们就可以跟踪现在选择的项目。

现在修改您的适配器代码,如下所示

// Attach a LongClick listener to the items's (row) view.
contactHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View view) {
        // Update the selectedArray. Set 1 for the selected item
        // and 0 for the others.
        updateSelectedArray(contactHolder.getAdapterPosition());

        if (selectedPos != RecyclerView.NO_POSITION) {
            if (recyclerItemClickListener != null) {
                recyclerItemClickListener.onItemLongClick(selectedPos, contactHolder.itemView);

                // Repopulate the list here
                notifyDatasetChanged();
            }
        }
        return true;
    }
});

onBindViewHolder

final int SELECTED = 1;
if(selectedArray[position] == SELECTED) {
    holder.itemView.setSelected(true);
} else {
    holder.itemView.setSelected(false);
}

您的updateSelectedArray()可能看起来像这样

private void updateSelectedArray(int position) {
    for(int i=0; i<selectedArray.length; i++){
        if(i == position) selectedArray[i] = 1;
        else selectedArray[i] = 0;
    }
}

从列表中删除项目后,您需要重置 selectedArray`,因为列表中的项目不再可用。

因此,您的deleteFromList功能可能如下所示:

private void deleteFromList(int position)
{
    yourList.remove(position);
    selectedArray = new int[yourList.size()];

    // Now re-initialize the Array with all zeros
    for(int i=0; i<selectedArray.length; i++)
        selectedArray[i] = 0;
}

我已采用数组来跟踪所选项目。但您可以使用ArrayList或任何您喜欢的数据结构来跟踪它。我们的想法是正确跟踪所选项目。

<强>更新

在列表中随机选择项目的问题是由于没有正确绑定您的视图。因此,当您删除项目时,您需要执行以下操作。

  • 重置selectedArray中的所选位置。即selectedPos = -1
  • 从列表中删除该项目。
  • 致电notifyDatasetChanged以了解您的更改效果 列表。

最重要的是,不要忘记设置else部分。我的意思是

// Pseudo code
if(position == selected) itemView.setSelected(true);
else itemView.setSelected(true); // Don't forget this else