有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。
当前回答
nhaarman答案的Kotlin实现:
mRecyclerView.addOnItemTouchListener(object : RecyclerItemClickListener(this, mRecyclerView,object :RecyclerItemClickListener.OnItemClickListener{
override fun onItemClick(view: View, position: Int) {
}
override fun onLongItemClick(view: View?, position: Int) {
}
}){})
RecyclerItemClickListener.java:
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
open class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {
private var mGestureDetector: GestureDetector
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onLongItemClick(view: View?, position: Int)
}
init {
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
return true
}
override fun onLongPress(e: MotionEvent) {
val child = recyclerView.findChildViewUnder(e.x, e.y)
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}
}
})
}
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView = view.findChildViewUnder(e.x, e.y)
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}
override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
其他回答
由于API已经发生了根本性的变化,如果你要为每个项目创建一个OnClickListener,这不会让我感到惊讶。不过也没那么麻烦。在你的RecyclerView的实现中。适配器<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);
}
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();
}
我是这样做的,没有不必要的类、检测器等。适配器中的简单代码。特别是针对longClick的更好解决方案。
public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.ViewHolder> {
private final ClickListener clickListener;
public PasswordAdapter(ClickListener clickListener) {
this.clickListener = clickListener;
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView name;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
name = (TextView) itemView.findViewById(R.id.card_name);
}
@Override
public void onClick(View v) {
int position = getBindingAdapterPosition();
if (position >= 0) {
clickListener.onItemClick(position, v);
}
}
@Override
public boolean onLongClick(View v) {
int position = getBindingAdapterPosition();
if (position >= 0) {
clickListener.onItemLongClick(position, v);
return true;
}
return false;
}
}
public interface ClickListener {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
}
然后在片段或活动中,点击:
PasswordAdapter mAdapter = new PasswordAdapter(
new PasswordAdapter.ClickListener() {
@Override
public void onItemClick(int position, View v) {
Log.d(TAG, "onItemClick position: " + position);
}
@Override
public void onItemLongClick(int position, View v) {
Log.d(TAG, "onItemLongClick pos = " + position);
}
}
);
这就是重用View的方法。OnClickListener:
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyviewHolder>
implements View.OnClickListener
在ViewHoder中获取项目布局的父视图:
public class MyviewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayout;
public MyviewHolder(View itemView) {
super(itemView);
linearLayout = itemView.findViewById(R.id.linear_layout_item);
}
}
在onBindViewHolder中设置标签为位置:
@Override
public void onBindViewHolder(MyviewHolder holder, int position) {
holder.linearLayout.setTag(position);
holder.linearLayout.setOnClickListener(this);
}
在你的onClick实现中:
@Override
public void onClick(View v) {
int position = (int) v.getTag();
switch (v.getId()) {
case R.id.linear_layout_item:
// do some thing with position
break;
}
}
有更简单的方法。只需要在根视图上应用onBindViewHolder中的click。
考虑这是你对适配器的看法,
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/linearlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:textSize="15sp" />
</LinearLayout>
然后在适配器中执行以下操作
//get the layout and make view holder
@Override
public RVAdapter.ViewHolder1 onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout, null);
ViewHolder1 viewHolder = new ViewHolder1(view);
return viewHolder;
}
@Override
public void onBindViewHolder(RVAdapter.ViewHolder1 holder, int position) {
//apply on click on your root view
holder.linearlayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Do on click stuff
}
});
}
//make references to views in layout including root view
public class ViewHolder1 extends RecyclerView.ViewHolder {
protected LinearLayout linearlayout = null
protected TextView textview = null;
public CareerLinksViewHolder(View itemView) {
super(itemView);
this.linearlayout = (LinearLayout) itemView.findViewById(R.id.linearlayout);
this.tvCompName = (TextView) itemView.findViewById(R.id.textview);
}
}
这个作品。
public class ServiceListAdapter extends RecyclerView.Adapter<ServiceListAdapter.ViewHolder> {
private final Context mContext;
private List<ServiceListModel> categoryList;
private View.OnClickListener onClickListener;
public ServiceListAdapter(Context mContext, List<ServiceListModel> categoryList, View.OnClickListener onClickListener) {
this.categoryList = categoryList;
this.mContext = mContext;
this.onClickListener = onClickListener;
}
@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final RowServiceListBinding binding = DataBindingUtil.inflate(inflater, R.layout.row_service_list, parent, false);
return new ViewHolder(binding.getRoot(), binding);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.binding.rlService.setOnClickListener(onClickListener);
holder.binding.rlService.setTag(position);
}
@Override
public int getItemCount() {
return categoryList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final RowServiceListBinding binding;
public ViewHolder(final View view, final RowServiceListBinding binding) {
super(view);
this.binding = binding;
}
@UiThread
public void bind(final ServiceListModel mAddressModel) {
//this.binding.setAddress(mAddressModel);
}
}
}
在活动/片段中使用
ServiceListAdapter adapter = new ServiceListAdapter(context, serviceList, new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.rlService:
int pos = (int) v.getTag();
serviceList.remove(position);
break;
}
}
});
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 碎片中的onCreateOptionsMenu
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?