簡體   English   中英

直接從RecyclerView按位置訪問ViewHolder

[英]Accessing a ViewHolder, directly from the RecyclerView, by position

我有一個RecyclerView,它顯示一系列從數據庫派生的視圖。 我希望通過突出顯示其邊緣來確認用戶已選擇其中一個視圖,並且我已經成功地做到了。 如果用戶繼續選擇其他選項,則希望刪除原始選擇中的突出顯示。 這是我遇到麻煩的地方。

最初的亮點是內部工作,就像我在做的一樣。 但是,我不知道如何僅使用其適配器位置訪問前一個視圖。 我一直在搜索StackOverflow大約一個小時,因為在Android API或google中找不到很多東西。 許多用戶似乎在問類似的問題,但最終,細微的差別使任何有用的答案都告一段落。

ViewHolder (這是RecyclerView的內部public class內部,我有一個OnClickListener ,如下所示:

@Override
    public void onClick(View view) {
        if(!selected) {
            selected = true;
            view.setBackgroundResource(R.drawable.default_selection_background);
        } else {
            selected = false;
            view.setBackgroundResource(0);
        }

        UpdateSelected(getAdapterPosition());
    }

這指向我的RecyclerView ,坦率地說,我尚未將任何工作代碼添加到我的UpdateSelected(int position)方法中。

如果有幫助,我打算使其具有以下功能:

void UpdateSelected(int position) {
    if(position != currentlySelected) {
        ViewHolder[currentlySelected].Deselect();
    }
}

public class ViewHolder extends RecyclerView.ViewHolder {
    ...

    public void Deselect() {
        // and from here, I can go on as normal.
    }
}

我注意到用戶建議其他用戶使用getLayoutPosition()來出於UI的目的獲取位置,除非他們特別希望繼續使用內部數據,這是我打算做的。

如何使用其位置從RecyclerView訪問特定的ViewHolder?

你可以做這樣的事情。

在您的適配器中,創建一個成員變量,該變量將跟蹤所選項目的位置。

 int selectedPosition = -1; // -1 some default value for nothing selected

然后在您的回收站視圖適配器的onBindViewHolder

  int backgroundRes = (position == selectedPosition)? R.drawable.default_selection_background : 0;
  view.setBackgroundResource(backgroundRes);

最后,在您的觀看者的onClick中

 @Override
 public void onClick(View view) {
   selectedPosition = getAdapterPosition();
   notifyDataSetChanged();
 }

您可以通過recyclerview的位置訪問該viewholder

這是我的實現

recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this,
                recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
               /*your coding */
            }

            @Override
            public void onItemLongClick(View view, int position) {

            }

        }));

並創建類

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {

    private OnItemClickListener mListener;
    private GestureDetector mGestureDetector;
    public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
        mListener = listener;

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
            @Override
            public void onLongPress(MotionEvent e) {
                View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());

                if (childView != null && mListener != null) {
                    mListener.onItemLongClick(childView, recyclerView.getChildPosition(childView));
                }
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildPosition(childView));
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
    public interface OnItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongClick(View view, int position);
    }
}

您無需手動交換背景資源,而可以將視圖標記為已選中或未選中,並讓Android使用可繪制的選擇器更改背景。

res / drawable / background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_selected="true" android:drawable="@drawable/default_selection_background" />
  <item android:drawable="@null" />
</selector>

background.xml將被設置為項目布局XML中的android:background

然后在您的onBindViewHolder(ViewHolder holder, int position)更新Android View的狀態:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    boolean isSelected = position == selectedPosition;
    holder.itemView.setSelected(isSelected);
}

對我來說,我更喜歡使用笨拙且邏輯較少的適配器。 您可以通過保留ViewModels列表(表示要在視圖中顯示的數據類的數據類-最多也不少)來實現,其中屬性之一可以是selected標志(在每個ViewModel中)。

當用戶選擇或取消選擇視圖時,回調將向演示者發出更新,演示者隨后更新適配器,並通知適配器哪些位置已更新。 這意味着將當前選定的項(最好是ID,但可以存儲ViewModel或位置)保留在演示者中,以便您可以對其進行更新。

暫無
暫無

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

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