android - 如何在 RecyclerView 上获得点击(不是 child )

标签 android android-layout android-recyclerview onclicklistener recyclerview-layout

有什么方法可以在 RecyclerView 上设置 onClickListener 吗?

我有一个 RecyclerView,里面有一些 child ,并在父级 RecyclerView 上设置了一个 OnClickListener。但是,当我单击该 View 时,onClick 不会触发。请参阅下面的示例代码——我们希望点击父级,不是子级。在这种情况下,我们不关心对项目的点击。

我已尝试对子项执行 setFocusable(false)setClickable(false)setOnClickListener(null) 但无济于事。在任何情况下,我都不认为 children 正在窃取 parent 的点击,因为当我点击没有 child 的区域时,点击也不会注册。

package com.formagrid.hellotest;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.Arrays;
import java.util.List;

public class HelloActivity extends Activity {

    private RecyclerView mRecyclerView;
    private RecyclerAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hello);

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdapter = new RecyclerAdapter(Arrays.asList("hi", "this", "is", "some", "text"));
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d("patricia", view.toString());
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.Holder> {

        public class Holder extends RecyclerView.ViewHolder {

            protected TextView textView;

            public Holder(TextView itemView) {
                super(itemView);
                this.textView = itemView;
            }

        }

        private List<String> contents;

        public RecyclerAdapter(List<String> contents) {
            this.contents = contents;
        }

        @Override
        public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new Holder(new TextView(parent.getContext()));
        }

        @Override
        public void onBindViewHolder(Holder holder, int position) {
            holder.textView.setText(contents.get(position));
        }

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

    }

}

最佳答案

Is there any way to set an onClickListener on a RecyclerView?

没有。也就是说,您可以设置一个OnClickListener,但RecyclerView 永远不会调用它。 RecyclerView 拦截所有触摸事件,但从不调用 performClick(),这是 View 调用其监听器的方式。

但是,您可以使用 OnTouchListenerGestureDetector 来模拟 OnClickListener。对于 GestureDetector 的监听器,我们可以使用 SimpleOnGestureListener,仅实现 onSingleTapUp() 方法。

class ClickListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Toast.makeText(HelloActivity.this, "Clicked", 0).show();
        return true;
    }
};

然后我们只需要将 OnTouchListener 中的 MotionEvent 提供给 GestureDetector,并检查返回值以决定是否使用该事件,以免干扰滚动、拖动等。

final GestureDetector detector = new GestureDetector(HelloActivity.this, new ClickListener());

mRecyclerView.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(detector.onTouchEvent(event)) {
                return true;
            }
            return false;
        }
    }
);

请注意,上面的解决方案几乎只适用于“简单的”RecyclerView,就像问题中描述和给出的那样。如果您使用更复杂的项目处理,例如拖放或滑动,我们将需要在触摸事件链的更上层处理我们的手势检测。

为此,我们可以子类化 RecyclerView 并在 dispatchTouchEvent() 方法中执行检测。如果检测到单击,我们只需调用 performClick(),这将触发 RecyclerViewOnClickListener

public class ClickableRecyclerView extends RecyclerView {

    private final GestureDetectorCompat detector;

    public ClickableRecyclerView(Context context) {
        this(context, null);
    }

    public ClickableRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        detector = new GestureDetectorCompat(context, new ClickListener());
    }

    private class ClickListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            performClick();
            return true;
        }
    };

    @Override
    public boolean dispatchTouchEvent(MotionEvent e) {
        detector.onTouchEvent(e);
        return super.dispatchTouchEvent(e);
    }
}

只需使用此子类代替您的常规 RecyclerView,并像往常一样在其上设置一个 OnClickListener。可能需要额外的构造函数,具体取决于您对其进行实例化的方式。

关于android - 如何在 RecyclerView 上获得点击(不是 child ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38256645/

相关文章:

android - TensorFlow 对象检测模型与股票模型一起正常工作,但失败并出现有关未实现已实现操作的错误

android - 无法从目录中读取文件 - android

android - 如何使用 jsoup android 获取特定标签

android - 如何使用运动布局在父 View 内缩放 textView?

android - 为什么 TextView 中的文本在回收器 View 中被截断?

c++ - 查找内存溢出

java - Android布局边距使宽度为0

java - 在布局内的 TextView 中动态设置文本 - Android

android - 当 RecyclerView 在 Dialog 上时不显示分隔符

java - 如何使 recyclerview 根据百分比仅显示一个数组?