【问题标题】:Getting a Reference to ViewHolder on RecyclerView Click在 RecyclerView Click 上获取对 ViewHolder 的引用
【发布时间】:2014-11-12 14:28:22
【问题描述】:

这是我第一次尝试实现RecyclerView。我在AdapterViewHolder 类之间实现了一个Callback 接口来处理UI 元素(按钮)上的点击事件。我在获取对单击发生的ViewHolder 的引用时遇到问题。我可以单击列表中第一项的Button,但是我定义的操作是在最后一个viewholder 上执行的我的回收站视图。我终于想通了通过我的界面传递位置,但我很难理解如何从中获取对该视图的引用。

    public class RoomAdapter extends RecyclerView.Adapter<RoomAdapter.RoomViewHolder>
{
    List<Room> mRooms;
    public RoomAdapter(List<Room> rooms) {
        mRooms = rooms;
    }

    @Override
    public RoomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        final View viewItem = LayoutInflater
                .from(viewGroup.getContext())
                .inflate(R.layout.room_rv_item,viewGroup,false);
        return vh = new RoomViewHolder(viewItem,new IRoomViewClick() {
            @Override
            public void editname(int pos) {

            }
        });
    }

    @Override
    public void onBindViewHolder(RoomViewHolder roomViewHolder, int i) {
        Room r = getItem(i);
        roomViewHolder.label.setText(r.name);


    }
    public Room getItem(int position)
    {
        return mRooms.get(position);
    }
    @Override
    public long getItemId(int position) {
        return mRooms.get(position).getId();
    }

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

    public static class RoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
    {
        TextView label;
        Button editBtn;
        LinearLayout labelView;
        Button saveBtn;
        Button deleteBtn;
        EditText editNameET;
        IRoomViewClick mListener;
        public RoomViewHolder(View itemView, IRoomViewClick listener) {
            super(itemView);
            labelView = (LinearLayout) itemView.findViewById(R.id.labelview);
            mListener = listener;
            editBtn =(Button) itemView.findViewById(R.id.editbtn);
            editBtn.setOnClickListener(this);
            label = (TextView) itemView.findViewById(R.id.room_listitem_label);

        }

        @Override
        public void onClick(View view) {
            int pos = getPosition();
            mListener.editname(pos);



        }
    }
    public static interface IRoomViewClick
    {
        public void editname(int pos);
    }

}

【问题讨论】:

  • 这不只是让我获得按钮的引用而不是 ViewHolder 本身吗?
  • 嘿...我没有仔细阅读问题...我认为您需要一个职位(因为我没有在您的代码中看到 getPosition() 的主体)...但是是的,你可以把 ViewHolder 放在那里......但是你不会知道位置,因为......好吧,它是 RecyclerView 并且视图/viewholder可以......回收......
  • 是的,我错过了在我的代码中实现 getPosition() 函数。那可能没有帮助。我仍然不完全清楚设置和获取标签,并将其转换为我可以操作的 ViewHolder。
  • 标签是一个对象。你可以放任何对象,但是在得到它之后你必须将它转换为适当的类
  • 我明白了,我在生命周期的哪个阶段设置和获取标签,我标记什么对象,我用什么标记它?

标签: android android-recyclerview


【解决方案1】:

您可以在onBindViewHolder 中为editBtn 设置标签:

    public RoomViewHolder(View itemView, IRoomViewClick listener) {
        ....
        editBtn =(Button) itemView.findViewById(R.id.editbtn);
        //add tag for this view
        editBtn.setTag(this);
        ....
   }

并在onClick获取它

    @Override
    public void onClick(View view) {
        //getTag
        RoomViewHolder holder = (RoomViewHolder )(view.getTag());
        int pos = getPosition();
        mListener.editname(pos);
    ...
    }

【讨论】:

  • 令人难以置信的是,谷歌没有想到更好的方法——几乎一年过去了,没有更好的方法可以通过旧的 setTag 方法(这是视图持有者非官方模式的一部分)获得 ViewHolder。 .
【解决方案2】:

实际上,通过在 RecyclerView 上调用 getChildViewHolder(View child),您可以做得比 getTag 更好:

@Override
public void onClick(View v) {
    MyHolder holder = (MyHolder) mRecyclerView.getChildViewHolder(v);
    holder.textView.setText("Clicked!");
}

【讨论】:

  • 它会给item中的所有views都可以访问还是只能点击item? github.com/CymChad/BaseRecyclerViewAdapterHelper/issues/594
  • 当视图被点击时,这个函数将访问被点击的那个视图。但除了它在onClick 处理程序中之外,它可以获取被点击或未被点击的视图。
  • 谢谢,我正在考虑获取位图表单 recyclerview 显示的可绘制图像视图以通过 whatsapp 共享!从缓存中获取图像工作正常,但速度很慢(使用 fresco )!!
  • 是的,如果您从缓存中获取,您正在访问数据库。如果您有一些小图像,最好保留它们。
【解决方案3】:
@Override
public void onClick(View v) {
    int pos = getAdapterPosition(); //getPosition() is deprecated 
    notifyItemChanged(pos);
}

notifyItemChanged 会通知你的 onBindViewHolder,然后你可以这样做

public void onBindViewHolder(RoomViewHolder roomViewHolder, int i) {
    Room r = getItem(i);
    roomViewHolder.label.setText(r.name);
    if(i == pos){ // Do Something }

}

当你点击该项目时,它会改变 pos' 的值并触发 // Do Something

【讨论】:

    【解决方案4】:

    原来RecycleView 将视图位置保存在视图布局参数中,因此如果您只是希望视图位置从列表中获取正确的项目,您可以使用此:

    RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) v.getLayoutParams();
    lp.getViewPosition();
    

    【讨论】:

    • getViewPosition 已弃用,您现在应该使用getViewLayoutPositiongetViewAdapterPosition,通常是后者。
    猜你喜欢
    • 2016-07-18
    • 2017-08-11
    • 2020-12-09
    • 1970-01-01
    • 2019-12-04
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多