RecyclerView onClick
有没有人使用RecyclerView
找到一种方法来设置一个onClickListener
项目在RecyclerView
? 我想为每个项目的每个布局设置一个监听器,但这看起来有点太麻烦了,我确信RecyclerView
有一个方法来监听onClick
事件,但是我无法弄清楚。
我们可以使用Java弱引用来做到这一点。 在语义上,视图持有者是应该对点击事件作出响应或者将其委托给正确的响应者的那个。
我们的目标:
- 除了实现一个特定的接口之外,Viewholder不应该对那些响应事件的类一无所知。
- 点击处理程序应该获得点击的视图的RecyclerView中的位置。
- 我们应该能够辨别视图持有者点击哪个视图。
- 保持所有组件之间的松散耦合并且不会导致任何保持周期。
脚步:
-
创建一个界面来处理点击响应。
-
在处理点击的活动中实现此接口。
-
在RecyclerView适配器中添加一个成员变量来容纳弱引用和一个设置它的构造函数。
-
在RecyclerView ViewHolder中执行相同的操作,并添加一个成员变量来跟踪位置。
-
在ViewHolder中的任何视图上设置点击监听器,然后回调给响应者来处理它们。
-
更改您的onBindViewHolder方法来设置绑定时的位置。
-
将响应者传递给ViewHolder。
-
在响应者中,您现在可以在视图上使用getId()来确定哪个视图被点击了。
下面是一个Gist,你可以看到它们是如何融合在一起的: RecyclerView点击处理
通常你的CardView
有多个元素,所以你需要一个布局视图来包装和组织它们。
您可以将OnClickListener
添加到该布局视图。
1.添加一个id到你的布局。 在这种情况下,一个LinearLayout
<android.support.v7.widget.CardView .....> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/card_view_linearLayout"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="name" android:id="@+id/card_view_name" /> ... </LinearLayout> </android.support.v7.widget.CardView>
$
2.在内部ViewHolder
类中获取布局视图。
public static class ViewHolder extends RecyclerView.ViewHolder{ private TextView nameView; ... private LinearLayout linearLayout; public ViewHolder(View itemView) { super(itemView); nameView = (TextView)itemView.findViewById(R.id.card_view_name); ... linearLayout = (LinearLayout)itemView.findViewById(R.id.card_view_linearLayout); } }
$
3.将监听器添加到onBindViewHolder
的布局,并使用回调将数据发送到Activity
或Fragment
(未测试)。
@Override public void onBindViewHolder(TrackAdapter.ViewHolder holder, final int position) { String str = mStringList.get(position); holder.nameView.setText(str); ... holder.linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { callback.itemCallback(mStringList.get(position)); } }); }
如何使用回调是另一回事
步骤1)编写点击界面
创建一个名为RecyclerViewClickListener.java的接口并添加下面的代码。 在这里我们声明两个方法onClick和onLongClick分别确定项目点击和长点击。
package com.androidtutorialshub.recyclerviewtutorial.Helper; import android.view.View; public interface RecyclerViewClickListener { void onClick(View view, int position); void onLongClick(View view, int position); }
步骤2)写下物品触摸类
创建一个名为RecyclerViewTouchListener.java的类并添加下面的代码。 在这里,我们编写逻辑来检测点击和长按回收查看项目。
package com.androidtutorialshub.recyclerviewtutorial.Helper; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; public class RecyclerViewTouchListener implements RecyclerView.OnItemTouchListener{ private GestureDetector gestureDetector; private RecyclerViewClickListener clickListener; public RecyclerViewTouchListener(Context context, final RecyclerView recyclerView, final RecyclerViewClickListener clickListener) { this.clickListener = clickListener; gestureDetector = 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 && clickListener != null) { clickListener.onLongClick(child, recyclerView.getChildPosition(child)); } } }); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { View child = rv.findChildViewUnder(e.getX(), e.getY()); if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) { clickListener.onClick(child, rv.getChildPosition(child)); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }
步骤3)定义点击监听器
打开MainActivity.java并更新下面的更改。 这里onClick()方法将检测点击项目和onLongClick将检测长期点击项目。
recyclerView.addOnItemTouchListener(new RecyclerViewTouchListener(getApplicationContext(), recyclerView, new RecyclerViewClickListener() { @Override public void onClick(View view, int position) { Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is clicked!", Toast.LENGTH_SHORT).show(); } @Override public void onLongClick(View view, int position) { Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is long pressed!", Toast.LENGTH_SHORT).show(); } }));
欲了解更多信息或下载源代码: – http://www.androidtutorialshub.com/android-recyclerview-click-listener-tutorial/
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() } }
试试这个,很简单。 它适用于我。 顺便说一句,我发现setOnClickListener
不会生效回收视图。
recycler.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { // anything todo } return true; } });