Java RecyclerView onClick

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24471109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:24:00  来源:igfitidea点击:

RecyclerView onClick

javaandroidandroid-recyclerviewonclickonclicklistener

提问by CurtJRees

Has anyone using RecyclerViewfound a way to set an onClickListenerto items in the RecyclerView? I thought of setting a listener to each of the layouts for each item but that seems a little too much hassle I'm sure there is a way for the RecyclerViewto listen for the onClickevent but I can't quite figure it out.

有没有人使用RecyclerView找到一种方法来设置中的onClickListener项目RecyclerView?我想为每个项目的每个布局设置一个侦听器,但这似乎有点麻烦我确信有一种方法RecyclerView可以侦听onClick事件,但我无法弄清楚。

采纳答案by nhaarman

As the API's have radically changed, It wouldn't surprise me if you were to create an OnClickListenerfor each item. It isn't that much of a hassle though. In your implementation of RecyclerView.Adapter<MyViewHolder>, you should have:

由于 API 已经发生了根本性的变化,如果您要OnClickListener为每个项目创建一个,我不会感到惊讶。不过也没有那么麻烦。在你的实现中RecyclerView.Adapter<MyViewHolder>,你应该有:

private final OnClickListener mOnClickListener = new MyOnClickListener();

@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
    view.setOnClickListener(mOnClickListener);
    return new MyViewHolder(view);
}

The onClickmethod:

onClick方法:

@Override
public void onClick(final View view) {
    int itemPosition = mRecyclerView.getChildLayoutPosition(view);
    String item = mList.get(itemPosition);
    Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}

回答by bolot

Check out a similar question@CommonsWare'scomment links to this, which implements the OnClickListenerinterface in the viewHolder.

查看一个类似的问题@CommonsWare'scomment links to this,它OnClickListenerviewHolder.

Here's a simple example of the ViewHolder:

下面是一个简单的例子ViewHolder

    TextView textView;//declare global with in adapter class

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

      private ViewHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            textView = (TextView)view.findViewById(android.R.id.text1);

      }

      @Override
      public void onClick(View view) {
            Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();

         //go through each item if you have few items within recycler view
        if(getLayoutPosition()==0){
           //Do whatever you want here

        }else if(getLayoutPosition()==1){ 
           //Do whatever you want here         

        }else if(getLayoutPosition()==2){

        }else if(getLayoutPosition()==3){

        }else if(getLayoutPosition()==4){

        }else if(getLayoutPosition()==5){

        }

        //or you can use For loop if you have long list of items. Use its length or size of the list as 
        for(int i = 0; i<exampleList.size(); i++){

        }


      }
  }

The Adapterthen looks like this:

Adapter则看起来是这样的:

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);

        return new ViewHolder(view);
    }

回答by Fifer Sheep

This is what I ended up needing, in case someone finds it useful:

这是我最终需要的,以防有人发现它有用:

public static class ViewHolder extends RecyclerView.ViewHolder {

    public ViewHolder(View item) {

        super(item);
        item.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("RecyclerView", "onClick:" + getAdapterPosition());
            }
        });

    }
}

Source: http://blog.csdn.net/jwzhangjie/article/details/36868515

来源:http: //blog.csdn.net/jwzhangjie/article/details/36868515

回答by Jacob Tabak

Here is a better and less tightly coupled way to implement an OnClickListenerfor a RecyclerView.

这是实现OnClickListenerfor a的更好且耦合度更低的方法RecyclerView

Snippet of usage:

使用片段:

RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
    new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
      @Override public void onItemClick(View view, int position) {
        // do whatever
      }

      @Override public void onLongItemClick(View view, int position) {
        // do whatever
      }
    })
);

RecyclerItemClickListenerimplementation:

RecyclerItemClickListener执行:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;


public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
  private OnItemClickListener mListener;

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

    public void onLongItemClick(View view, int position);
  }

  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 child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null && mListener != null) {
                mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
            }
        }
    });
}

  @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.getChildAdapterPosition(childView));
      return true;
    }
    return false;
  }

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

  @Override
  public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}

回答by 4gus71n

For me, this is the best way:

对我来说,这是最好的方法:

class YourRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> implements View.OnClickListener { 
  ...
  @Override
  public void onClick(View view) {
        int itemPosition = vRecycle.getChildPosition(view);
        //And use itemPosition to get the item from your collection. This way you dont restrain the ViewHolder with a OnClick callback
    }
  ...
}

回答by Jawnnypoo

All the answers posted so far are great solutions, however if you do not want to deal with too many implementation details, and just want it to work similarly to how ListView does, I would recommend using TwoWay-View, as seen here:

到目前为止发布的所有答案都是很好的解决方案,但是如果您不想处理太多的实现细节,而只是希望它的工作方式与 ListView 的工作方式类似,我建议使用 TwoWay-View,如下所示:

https://github.com/lucasr/twoway-view

https://github.com/lucasr/twoway-view

Note that this implementation also supports long press on items, as well as support for pressed states (which is something important that other solutions to this question lack).

请注意,此实现还支持长按项目,以及支持按下状态(这是该问题的其他解决方案所缺乏的重要内容)。

If you don't want to use the entire library, take a look at the ClickItemTouchListenerclass, which can be used as a standalone if needed. The only issue I found with it at the moment is with long press + scrolling, it seems to have incorrect behaviour.

如果您不想使用整个库,请查看ClickItemTouchListener类,如果需要,可以将其用作独立的类。我目前发现的唯一问题是长按 + 滚动,它似乎有不正确的行为。

回答by Bubunyo Nyavor

This is what worked for me. Attach the OnClickListenerto the onBindView. I don't really know if this will impact the performance, but it seems to work fine with little code.

这对我有用。将 附加OnClickListeneronBindView. 我真的不知道这是否会影响性能,但它似乎用很少的代码就可以正常工作。

public void onBindViewHolder(ViewHolder holder, final int position) {
    holder.view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
            }
    });
}

回答by Eng.Fouad

Based on Jacob Tabak's answer (+1 for him), I was able to add onLongClick listener:

根据 Jacob Tabak 的回答(他为 +1),我能够添加 onLongClick 侦听器:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    public interface OnItemClickListener {
        void onItemClick(View view, int position);

        void onItemLongClick(View view, int position);
    }

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

        return false;
    }

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

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}

Then you can use it like this:

然后你可以像这样使用它:

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

    @Override
    public void onItemLongClick(View view, int position) {
        // ...
    }
}));

回答by u2gilles

Here is what I did. This solution supports both onClick and onLongClick on both RecyclerView Items and Views insides RecyclerView Items (internal views).

这是我所做的。该解决方案支持 RecyclerView Items 和 RecyclerView Items 内部的 Views(内部视图)上的 onClick 和 onLongClick。

I tag viewHolder on the views of my choice :

我在我选择的视图上标记 viewHolder :

public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, null);
    ViewHolder viewHolder = new ViewHolder(itemView);

    itemView.setOnClickListener( this);
    itemView.setOnLongClickListener(this);
    viewHolder.imageIV.setOnClickListener(this);
    viewHolder.imageIV.setOnLongClickListener(this);

    viewHolder.imageIV.setTag(viewHolder);
    itemView.setTag(viewHolder);

    return viewHolder;
}

And I use holder.getPosition() to retrieve the position in onClick() method (onLongClick is similar) :

我使用 holder.getPosition() 来检索 onClick() 方法中的位置(onLongClick 类似):

public void onClick(View view) {
    ViewHolder holder = (ViewHolder) view.getTag();
    int position = holder.getPosition();

    if (view.getId() == holder.imageIV.getId()){
        Toast.makeText(context, "imageIV onClick at" + position, Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(context, "RecyclerView Item onClick at " + position, Toast.LENGTH_SHORT).show();
    }
}

A variant with getChildPosition also works. Please note that for the internal views, in onClick() use :

带有 getChildPosition 的变体也有效。请注意,对于内部视图,在 onClick() 中使用:

int position = recyclerView.getChildPosition((View)view.getParent());

To my mind, the avantage of this solution is that when one clicks on the image, only the onclick() image listener is called whereas when I combined Jacob's solution for a RecyclerView Item view and my solution for internal views the RecyclerView Item view onclick() is also called (when click on image).

在我看来,这个解决方案的优点是,当单击图像时,只调用 onclick() 图像侦听器,而当我将雅各布的 RecyclerView Item 视图解决方案和我的内部视图解决方案组合在一起时,RecyclerView Item 视图 onclick( ) 也称为(单击图像时)。

回答by Lone_iqbal

here is complete code for my custom adapter this code will inflate the rows with list items defined in the xml file named "list_item" it will also perform click event on all list items rows with respective positions.

这是我的自定义适配器的完整代码,此代码将使用名为“list_item”的 xml 文件中定义的列表项来扩充行,它还将对具有相应位置的所有列表项行执行单击事件。

public class MyCustomAdapter extends RecyclerView.Adapter`<`AdapterMyCustomAdapter.ViewHolder> {

    public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
        public onItemClickListener mListener;
        public ViewHolder(View v, onItemClickListener listener) {
            super(v);
            mListener =listener;
            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            mListener.onRecyclerItemClick(v, getPosition());
        }

        public static interface onItemClickListener {
            public void onRecyclerItemClick(View view , int position);
        }
    }

    @Override
    public int getItemCount() {
        return 5;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int pos) {      

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);

    /* here list_item is an xml file we want to inflate ...it is same as we do in case of listview for customization.*/

        MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {

            @Override
            public void onRecyclerItemClick(View view, int position) {
                System.out.println("clicked on list item at position " +position);
            } 
        });
        return vh;
    }
}