如何获得RecyclerView(不是孩子)的点击

时间:2016-07-07 23:07:50

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

有没有办法在onClickListener上设置RecyclerView

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

我尝试对孩子们进行setFocusable(false)setClickable(false)setOnClickListener(null)无济于事。在任何情况下,我都认为孩子们没有从父母那里窃取点击,因为当我点击没有孩子的区域时,点击也不会注册。

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

    }

}

5 个答案:

答案 0 :(得分:4)

  

有没有办法在onClickListener上设置RecyclerView

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

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

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

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

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

请注意,上述解决方案几乎只适用于简单的&#34; RecyclerView,就像问题中描述和给出的那样。如果您正在使用更多涉及的项目处理,例如拖放或滑动,我们需要在触摸事件链稍微进一步处理我们的手势检测。

为此,我们可以继承RecyclerView并在dispatchTouchEvent()方法中执行检测。如果检测到单击,我们只需拨打performClick()即可点击RecyclerView 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。可能需要其他构造函数,具体取决于您如何实例化它。

答案 1 :(得分:1)

尝试在recyclayout或linearlayout或FrameLayout中包装您的recyclerview,然后将click监听器设置为relativelayout / linearlayout / framelayout。

<RelativeLayout
   android:id="@+id/myLayout"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">
   <android.support.v7.widget.RecyclerView
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
   </android.support.v7.widget.RecyclerView>
</RelativeLayout>

现在:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.myLayout);
rl.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         Log.d("patricia", view.toString());
    }
});

答案 2 :(得分:1)

这就是我用科特林风格所做的

fun RecyclerView.enableClickListener(){
    val gesture = object : GestureDetector.SimpleOnGestureListener(){
        override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
            this@enableClickListener.performClick()
            return super.onSingleTapConfirmed(e)
        }
    }
    val detector = GestureDetector(this.context, gesture)
    this.setOnTouchListener { v, event -> detector.onTouchEvent(event) }
}

这是使用方法

yourRecyclerView.apply {
        enableClickListener()
        setOnClickListener {
           // Do what you want  ...
        }
    }

享受:)

答案 3 :(得分:0)

这是个把戏,欢迎大家发表评论。

FrameLayout中可以有2个子项。第一个是RecyclerView,第二个是View

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <View
            android:id="@+id/over_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    </FrameLayout>

由于它是FrameLayout,所以View将位于RecyclerView的上方,并且您可以将onClickListener设置为View,其行为将如果是点击的RecyclerView

over_view.setOnClickListener {
    .....
}

答案 4 :(得分:-1)

RecycleView上的点击事件?试试这样:

Dialog