簡體   English   中英

RecyclerView 項目不重復,但保留其插槽中先前項目的更改

[英]RecyclerView items not repeating, but retaining changes of previous item that was in its slot

我正在嘗試實現可以從 RecyclerView 適配器 class 中選擇的文件列表。 雖然我知道這不是一個好主意,但我覺得如果我能夠從所說的 class 中實現這一點,這對未來會很有幫助。 我的列表項(RecyclerView 的每個單獨項視圖)具有以下結構:

|--------|----------------|
|  ICON  |      DATA      |
|--------|----------------|
  • 問題:

    • 選擇文件時(通過觸摸文件項的圖標部分),我將該項目的背景更改為另一種顏色以表示它已被選中。

    • 但是,當我稍后向下滾動到大約 25 個項目時,另一個文件具有相同的背景顏色,即使它沒有被選中(它沒有在 Log.d 中顯示為被選中,也沒有在用於存儲的測試 ArrayList選定的文件)。

    • 似乎該項目僅保留了先前居住者的背景變化。

  • 解決方案嘗試:

    • 以前,只有與每個列表項相關的變量在 RecyclerView ViewHolder class 中聲明,所有更改都在 onBindViewHolder 方法中進行。 現在,所有要進行的更改都已移至名為 bind 的方法中的 ViewHolder class。 行為沒有變化。

    • 如果我在 onBindViewHolder 的第一步中設置默認背景圖像,則行為會發生變化,因此項目不會保留先前占用者的更改。 但是,在向后滾動時,目標項目的背景更改將恢復為默認背景圖像。

  • 代碼:

public class RVA extends RecyclerView.Adapter<RVA.RVH>
{
    private LayoutInflater inf;
    private ArrayList<File> items;

    // The var below is used to track the no. of selected items
    // globally within the RVA class.
    private int numberOfSelectedItems = 0; 

    public RVA(ArrayList<File> _items)
    {
        items = _items;
    }

    @Override
    public RVA.RVH onCreateViewHolder(ViewGroup parent, int viewType)
    {
        inf = LayoutInflater.from(parent.getContext());
        return new RVH(inf, parent);
    }

    @Override
    public void onBindViewHolder(RVA.RVH holder, int position)
    {
        File listItem = items.get(position);

        // 'binding' each file element to a respective host container.
        holder.bind(listItem);
    }

    @Override
    public int getItemCount()
    {
        return items.size();
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    // The ViewHolder class.
    // Initially it was just declared as class.
    // There was no change observed after the 'final' modifier was added.
    final class RVH extends RecyclerView.ViewHolder
    {
        private Context context;
        private LinearLayout itemSelector;
        private ImageView itemIcon;
        private TextView itemName;
        private TextView itemSize;

        public RVH(LayoutInflater inf, ViewGroup parent)
        {
            super(inf.inflate(R.layout.list_item, parent, false));
            context = parent.getContext();

            // This is the SECOND outermost LinearLayout of each file item View.
            // It was previously the parent Layout, but there was no difference due to change.
            itemSelector = itemView.findViewById(R.id.item_selector);

            // This is the icon ImageView.
            itemIcon = itemView.findViewById(R.id.item_icon);

            // These are the data TextViews.
            itemName = itemView.findViewById(R.id.item_id);
            itemSize = itemView.findViewById(R.id.item_size);
        }

        // The 'bind' method that registers changes.
        public void bind(File fileItem)
        {
            String listItemName = fileItem.getName();
            itemName.setText(listItemName);

            //---- These are just changes to the icons depending on type. Works fine.
            if(fileItem.isDirectory())
            {
                itemIcon.setImageResource(R.drawable.directory_icon);
                itemSize.setText("Directory");
            }
            else
            {
                itemSize.setText(fileItem.length() + " B");
                if(listItemName.endsWith(".jpg") || listItemName.endsWith(".jpeg") || listItemName.endsWith(".png") || listItemName.endsWith(".gif"))
                {
                    Glide.with(context).load(fileItem).centerCrop().into(itemIcon);
                }
                else
                {
                    itemIcon.setImageResource(R.drawable.file_icon);
                }
            }
            //---- END

            //---- This is the code which handles opening files according to type. Works fine.
            itemSelector.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    if(numberOfSelectedItems == 0)
                    {
                        if(!itemSize.getText().toString().endsWith(" B"))
                        {
                            Intent loadListItemIntent = new Intent(context, DirectoryViewActivity.class);
                            loadListItemIntent.putExtra("ITEMPATH", fileItem.getPath());
                            context.startActivity(loadListItemIntent);
                        }
                        else
                        {
                            if(itemName.getText().toString().endsWith(".jpg") || itemName.getText().toString().endsWith(".jpeg") || itemName.getText().toString().endsWith(".png") || itemName.getText().toString().endsWith(".gif"))
                            {
                                Glide.with(context).load(fileItem).centerCrop().into(itemIcon);
                                Intent loadListItemIntent = new Intent(context, ImageActivity.class);
                                loadListItemIntent.putExtra("ITEMPATH", fileItem.getPath());
                                context.startActivity(loadListItemIntent);
                            }
                            else
                            {
                                Toast.makeText(context, "File needs proper application.", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                }
            });
            //---- END

//---- !!! THIS SECTION is where the problem manifests.
            itemIcon.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    if(itemIcon.getTag().toString().equals("not_selected"))
                    {
                        // Incrementing based on selection.
                        ++numberOfSelectedItems;

                        // Using a tag to identify/ denote whether item is selected.
                        itemIcon.setTag("selected");

                        // Changing the background & disabling file opening while in selection mode.
                        itemSelector.setBackgroundResource(R.drawable.list_item_selected);
                        itemSelector.setClickable(false);
                        itemSelector.setLongClickable(false);

                        // I use this odd method to send a message to the host Activity
                        // that we have entered selection mode & that the Activity should
                        // display some option buttons on the Action Bar.
                        if(context instanceof DirectoryViewActivity)
                        {
                            ((DirectoryViewActivity)context).addSelectedItem(fileItem);
                            if(numberOfSelectedItems == 1)
                            {
                                ((DirectoryViewActivity)context).setSelectionMode();
                            }
                        }
                    }
                    else
                    {
                        // Decrementing based on deselection.
                        --numberOfSelectedItems;

                        // Overwiting the tag to identify/ denote item is now unselected.
                        itemIcon.setTag("not_selected");

                        // Background changed back to default & file opening re-enabled.
                        itemSelector.setClickable(true);
                        itemSelector.setLongClickable(true);
                        itemSelector.setBackgroundResource(R.drawable.list_item_background);

                        // I use this method to send a message to the host Activity
                        // that we have exited selection mode & that the Activity should
                        // remove related option buttons from the Action Bar.
                        if(context instanceof DirectoryViewActivity)
                        {
                            ((DirectoryViewActivity)context).removeSelectedItem(fileItem);
                            if(numberOfSelectedItems == 0)
                            {
                                ((DirectoryViewActivity)context).voidSelectionMode();
                            }
                        }
                    }
                }
            });
        }
    }
}

這是因為RecyclerView不會為列表中的所有項目創建視圖,它會創建足夠的ViewHolder來填滿屏幕,並且當您滾動舊的ViewHolder時,它會綁定到適配器中的其他一些數據,即onBindViewHolder()被調用,所以基本上這里發生的是您在屏幕上設置當前ViewHolder的背景,並且當您滾動相同的ViewHolder以綁定到新數據時。

我認為您必須在onBindViewHolder中檢查這是否是您要為其設置背景的項目,然后如果未在數據集集背景中選擇該項目(如果已選擇),則決定將其刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM