Как получить клики на RecyclerView (НЕ дети)

Есть ли способ установить 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(); } } } 

Есть ли способ установить onClickListener в RecyclerView ?

Нет. То есть вы можете установить OnClickListener , но RecyclerView никогда не вызовет его. RecyclerView перехватывает все события касания, но никогда не вызывает performClick() , которая представляет собой представление View своего слушателя.

Вы можете, однако, имитировать OnClickListener с помощью OnTouchListener и 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 s из OnTouchListener и проверить возврат, чтобы решить, следует ли потреблять событие, чтобы не мешать прокрутке, перетаскиванию и т. Д.

 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() , которая OnClickListener RecyclerView .

 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 на нем, как обычно. Дополнительные конструкторы могут быть необходимы, в зависимости от того, как вы это создаете.

Попробуйте что-то вроде обертывания вашего recyclerview внутри relativelayout или linearlayout или FrameLayout, а затем установите прослушиватель кликов в 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()); } }); 

Событие click на RecycleView? Попробуйте вот так:

 //set android:descendantFocusability="blocksDescendants" on parent layout //then setOnClickListener <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" **android:descendantFocusability="blocksDescendants"** android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </LinearLayout>