Android RecyclerView:为什么列表中的第一项已被选中? [英] Android RecyclerView: why is first item in list already selected?

查看:56
本文介绍了Android RecyclerView:为什么列表中的第一项已被选中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a RecyclerView list of CardViews with a defaultbackground of white. I set up a OnLongClickListener to select the CardView and load a DialogFragment to confirm deletion for the item (CardView) and change the background color to red.

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

Everything is working correctly except the first CardView created in the list is already showing a red background even though the user has not OnLongClicked the CardView. Thereafter, the newest CardView added always shows the red background even when the user has not yet OnLongClicked the CardView. What am I missing here?

background_selector.xml:

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:

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());
}             

推荐答案

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

You need to declare an external array to keep track of the items selected. Let us have an array which have the same size as the list.

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;

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

Now inside your adapter, when an item is clicked, set 1 in the proper position in the selectedArray. So that, we can keep track which item is selected now.

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

Now modify your adapter code as follows

// 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`,因为该项目在列表中不再可用.

And after you delete an item from the list, you need to reset the selectedArray` as the item is no longer available in your list.

所以您的deleteFromList函数可能类似于:

So your deleteFromList function may look like:

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或任何您喜欢的数据结构来跟踪它.这个想法是正确地跟踪选定的项目.

I've taken an array to keep track of the selected item. But you can take an ArrayList or any data structure you like to keep track of it. The idea is to keep track of the selected item properly.

更新

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

The problem of having randomly selected items in your list is caused by not binding your views properly. So when you delete an item, you need to do the following things.

  • 重置您在selectedArray中的所选位置.即selectedPos = -1
  • 从列表中删除该项目.
  • 致电notifyDatasetChanged以使您所做的更改生效 列表.
  • Reset your selected position in the selectedArray. i.e. selectedPos = -1
  • Remove the item from the list.
  • Call notifyDatasetChanged to take the effect of your changes in the list.

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

And most importantly don't forget to set the else part. What I meant is

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

这篇关于Android RecyclerView:为什么列表中的第一项已被选中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆