直接从RecyclerView访问ViewHolder,按位置

时间:2016-10-03 10:48:54

标签: java android android-recyclerview android-viewholder

我有一个RecyclerView,它显示从数据库派生的一系列视图。我希望确认用户通过突出显示其边缘来选择其中一个视图,并且我已成功完成此操作。如果用户继续选择不同的选项,我希望删除原始选择上的突出显示。这是我遇到一些麻烦的地方。

最初的亮点不是麻烦,正如我在内部所做的那样。但是,我不知道如何仅使用其适配器位置访问上一个视图。我一直在搜索StackOverflow大约一个小时,因为我在Android API或google中找不到太多东西。许多用户似乎在问类似的问题,但最终,微妙的差异使任何有用的答案都无效。

在我的ViewHolder内部public class内部RecyclerView,我有一个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()来获取用户界面的位置,除非他们特别希望继续使用内部数据,这是我打算做的。

如何使用其位置从我的RecyclerView访问特定的ViewHolder?

3 个答案:

答案 0 :(得分:1)

你可以这样做。

在适配器中,创建一个成员变量,该变量将跟踪所选项目的位置。

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

然后在您的onBindViewHolder循环器视图适配器

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

最后点击你的观众

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

答案 1 :(得分:1)

您可以通过recyclelerview

的位置访问查看者

以下是我的实施

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) {

            }

        }));

并创建Class

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

答案 2 :(得分:0)

不是手动交换背景资源,而是将视图标记为已选择,并让Android使用可绘制选择器更改背景。

RES /抽拉/ 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视图的状态:

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

对我来说,我更喜欢有一个笨重且逻辑较少的适配器。您可以通过保留ViewModel列表(表示您将在视图中显示的内容的数据类 - 不多也不少)来实现此目的,其中一个属性可以是选定的标志(在每个ViewModel中)。

当用户选择或取消选择View时,回调会向演示者发出更新,演示者随后会更新适配器,并通知适配器哪些位置已更新。这意味着保留当前所选项目(最好是ID,但可以存储ViewModel或位置),以便您可以更新它。