有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。


当前回答

这里有一个更好的和不那么紧密耦合的方式来实现一个OnClickListener的RecyclerView。

用法片段:

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

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

其他回答

我已经看了所有的答案,并不是很满意。我找到了更简单快捷的方法。想分享给未来的读者。

选择单个回收项目中的任何视图。 获取这个View的父视图(确保你施放了合适的ViewGroup) 将onClickListener设置为这个父节点。

示例代码(它是在适配器的onBindViewHolder方法中编写的):

@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {

    ConstraintLayout parent = (ConstraintLayout) holder.title.getParent();
    parent.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(context, "Clicked recycler view item at position " + position, Toast.LENGTH_SHORT).show();
        }
    });
}

查看类似的问题@CommonsWare的评论链接到this,它在viewHolder中实现了OnClickListener接口。

下面是ViewHolder的一个简单例子:

/** Declare global with in adapter class. */
TextView textView;

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 RecyclerView. */
        if (getLayoutPosition() == 0) {
           // Do whatever you want here
        } else if(getLayoutPosition() == 1) { 
           // Do whatever you want here
        } else if(getLayoutPosition() == 2) {
           // Do whatever you want here
        }

        /** Or you can use For loop if you have long list of items. */
        for (int i = 0; i < exampleList.size(); i++) {
            // Do whatever you want here
        }
    }
}

在你的RecyclerView中创建ViewHolder。适配器看起来像这样:

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

Recyclerview适配器与kotlin

在适配器中可以通过两种方式实现项目点击监听器。

第一种方法是使用界面

在你的活动课上:

class YourActivity : AppCompatActivity(), TestAdapter.ClickListener {
...
override fun itemClicked() {

}
...
}

在适配器类中:

class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder> {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
     holder.textView1.setOnClickListener { 
        clickListener.itemClicked(position) 
     }
}
...
interface ClickListener {
     fun itemClicked(position : Int)
}
...
}

第二种方法是使用callBack调用

在适配器类中:

class MyAdapter(val callBack: (pos:Int) -> Unit) : RecyclerView.Adapter<MyAdapter.MyViewHolder> {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
     holder.textView1.setOnClickListener { 
        callBack(position)
     }
}
}

在你的活动课上:

class YourActivity : AppCompatActivity() {
...
val testAdapter = TestAdapter(
            callBack = { index ->
               
            })
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = testAdapter
...
}

这里有一个更好的和不那么紧密耦合的方式来实现一个OnClickListener的RecyclerView。

用法片段:

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

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

在Kotlin中也是如此

inner class MyViewHolder(v: View, myOnClickListener: MyOnClickListener) : RecyclerView.ViewHolder(v) {
    init {
        v.setOnClickListener { v -> myOnClickListener.onClick(v, adapterPosition) }
    }
}

override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MyViewHolder {
    val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.myview, viewGroup, false)
    return MyViewHolder(view, mOnClickListener)
}

inner class MyOnClickListener {
    fun onClick(view: View, position: Int) {
        val item = mList[position]
        Toast.makeText(view.context, item, Toast.LENGTH_LONG).show()
    }
}