如何获得RecyclerView的点击(不是孩子) [英] How to get clicks on RecyclerView (NOT the children)

查看:70
本文介绍了如何获得RecyclerView的点击(不是孩子)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在RecyclerView上设置onClickListener?

我有一个RecyclerView,其中有一些孩子,并在父RecyclerView上设置了OnClickListener.但是,当我单击该视图时,不会触发onClick.请参阅下面的示例代码-我们希望点击父级,子级.在这种情况下,我们不在乎对项目的点击.

I have a RecyclerView with some children in it, and setting an OnClickListener on the parent RecyclerView. However, the onClick doesn't fire when I click on that view. See sample code below -- we want to get clicks on the parent, NOT the children. In this scenario we don't care about clicks on the items.

我尝试对孩子进行setFocusable(false)setClickable(false)setOnClickListener(null)无济于事.无论如何,我都不认为孩子会从父母那里窃取点击,因为当我单击没有孩子的区域时,这些点击也不会注册.

I have tried doing setFocusable(false), setClickable(false), and setOnClickListener(null) on the children to no avail. In any case I don't think the children are stealing clicks from the parent, because when I click on the area where there is no children, the clicks don't register either.

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

    }

}

推荐答案

是否可以在RecyclerView上设置onClickListener?

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

No. That is, you can set an OnClickListener, but RecyclerView will never call it. RecyclerView intercepts all touch events, but never calls performClick(), which is how View invokes its listener.

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

You can, however, simulate an OnClickListener with an OnTouchListener and a GestureDetector. For the GestureDetector's listener, we can use a SimpleOnGestureListener, implementing just the onSingleTapUp() method.

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

然后,我们只需要从OnTouchListener提供GestureDetectorMotionEvent,并检查返回值以决定是否使用该事件,以免干扰滚动,拖动等.

Then we just need to feed the GestureDetector the MotionEvents from an OnTouchListener, and check the return to decide whether to consume the event, so as to not interfere with scrolling, dragging, etc.

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,就像问题中描述和给出的一样.如果您使用的是涉及更多内容的项目处理(例如拖放或滑动),则我们需要在触摸事件链的上游进行手势检测.


Please note that the above solution works with pretty much only a "simple" RecyclerView, like the one described and given in the question. If you're using more involved item handling, like drag and drop or swipe, we'll need to handle our gesture detection a little further up the touch event chain.

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

To do this, we can subclass RecyclerView and perform the detection in the dispatchTouchEvent() method. If a single tap is detected, we simply call performClick(), which will fire the RecyclerView's OnClickListener.

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.可能需要其他构造函数,具体取决于您如何实例化它.

Just use this subclass in place of your regular RecyclerView, and set an OnClickListener on it as you normally would. Additional constructors may be necessary, depending on how you're instantiating this.

这篇关于如何获得RecyclerView的点击(不是孩子)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆