Parent click event not firing when recyclerview clicked

匿名 (未验证) 提交于 2019-12-03 02:30:02

问题:

I have a RecyclerView which is in a CardView that has a couple of TextViews. The CardView has a OnClickListener set and is fired off when clicking on the TextViews, but does not fire when clicking on the RecyclerView.

Here is what the CardView looks like:

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:card_view="http://schemas.android.com/apk/res-auto"     android:id="@+id/card_view"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:layout_margin="5dp"     card_view:cardCornerRadius="4dp"     card_view:cardElevation="5dp">      <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:orientation="vertical"         android:weightSum="100"         android:minWidth="100dp">          <TextView             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:textAppearance="?android:attr/textAppearanceLarge"             android:id="@+id/text1"             android:textColor="@color/abc_primary_text_material_light"             android:layout_weight="1"             android:layout_gravity="center_horizontal" />          <android.support.v7.widget.RecyclerView             android:id="@+id/recyclerView"             android:layout_width="match_parent"             android:layout_height="0dp"             android:listSelector="@color/highlighted_text_material_light"             android:layout_weight="98" />          <View             android:layout_width="match_parent"             android:layout_height="1dp"             android:background="@android:color/black" />          <RelativeLayout             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:id="@+id/relativeSummary"             android:orientation="horizontal"             android:layout_weight="1">              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:textAppearance="?android:attr/textAppearanceLarge"                 android:id="@+id/text2"                 android:textAlignment="viewEnd"                 android:textColor="@color/abc_secondary_text_material_light"                 android:layout_marginLeft="5dp"                 android:layout_marginRight="5dp"                 android:gravity="start"                 android:singleLine="true"                 android:layout_alignParentLeft="true" />              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:textAppearance="?android:attr/textAppearanceLarge"                 android:id="@+id/text3"                 android:textColor="@color/abc_primary_text_material_light"                 android:layout_marginRight="5dp"                 android:layout_marginLeft="5dp"                 android:gravity="end"                 android:singleLine="true"                 android:layout_alignParentRight="true"                 android:layout_toRightOf="@+id/text2" />          </RelativeLayout>     </LinearLayout> </android.support.v7.widget.CardView> 

I do not need a click listener on this RecyclerView and really only need the parent view's click event to fire when the RecyclerView is clicked (The same goes for the OnLongClick event). I also need the RecyclerView to scroll. Is the RecyclerView some how eating the click event and not passing it up to the parent?

回答1:

There is a better solution. That is, subclass your CardView:

public class InterceptTouchCardView extends CardView {      public InterceptTouchCardView(Context context) {         super(context);     }      public InterceptTouchCardView(Context context, AttributeSet attrs) {         super(context, attrs);     }      public InterceptTouchCardView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }      /**      * Intercept touch event so that inner views cannot receive it.      *       * If a ViewGroup contains a RecyclerView and has an OnTouchListener or something like that,      * touch events will be directly delivered to inner RecyclerView and handled by it. As a result,       * parent ViewGroup won't receive the touch event any longer.      */     @Override     public boolean onInterceptTouchEvent(MotionEvent ev) {         return true;     } } 


回答2:

recyclerView.setLayoutFrozen(true); 

just setLayoutFrozen true after setAdapter for recyclerView



回答3:

In my case, I had a CardView with a couple of buttons and a RecyclerView. With the solutions of ywwynm and Daryl the problem was that the CardView would intercept the events from all of its child views, including the buttons. But what I wanted was for the CardView to intercept the touch events of the RecyclerView only. My solution was the following:

public class UntouchableRecyclerView extends RecyclerView {      public UntouchableRecyclerView(Context context) {         super(context);     }      public UntouchableRecyclerView(Context context, AttributeSet attrs) {         super(context, attrs);     }      public UntouchableRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }      @Override     public boolean onTouchEvent(MotionEvent e) {         return false;     } } 


回答4:

I figured out how to get the click event to the RecyclerView's parent. My solution kind of feels like a hack, so I'm hoping that someone can come up with a better solution.

In the RecylerView.Adapter:

@Override public ViewHolder onCreateViewHolder(final ViewGroup viewGroup, int i) {     View view = LayoutInflater.from(viewGroup.getContext())             .inflate(R.layout.my_item_layout, viewGroup, false);      ViewHolder viewHolder = new ViewHolder(view);      viewHolder.itemView.setOnClickListener(new View.OnClickListener() {         @Override         public void onClick(View v) {             viewGroup.callOnClick();         }     });     viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {         @Override         public boolean onLongClick(View v) {             return viewGroup.performLongClick();         }     });      return viewHolder; } 

I then had to hook up the click event on the RecyclerView:

RecyclerView.setOnClickListener(new View.OnClickListener() {     @Override     public void onClick(View v) {         parentView.callOnClick();     } }); RecyclerView.setOnLongClickListener(new View.OnLongClickListener() {     @Override     public boolean onLongClick(View v) {         return parentView.performLongClick();     } }); 


回答5:

@ywwynm, you are on the right track except the solution doesn't allow the nested RecyclerView to scroll. I combined it with the solution here and came up with this solution to handle click and onLongClick events as well as to allow scrolling.

public class InterceptTouchCardView extends CardView {     private GestureDetector mGestureDetector;     private boolean mLongClicked;      public InterceptTouchCardView(Context context) {         super(context);         Initialize();     }      public InterceptTouchCardView(Context context, AttributeSet attrs) {         super(context, attrs);         Initialize();     }      public InterceptTouchCardView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         Initialize();     }      private void Initialize() {         mGestureDetector = new GestureDetector(getContext(),                 new GestureDetector.SimpleOnGestureListener() {                     public boolean onDown(MotionEvent e) {                         mLongClicked = false;                         return true;                     }                      public void onLongPress(MotionEvent e) {                         mLongClicked = true;                         performLongClick();                     }                 });     }      /**      * Intercept touch event so that inner views cannot receive it.      *      * If a ViewGroup contains a RecyclerView and has an OnTouchListener or something like that,      * touch events will be directly delivered to inner RecyclerView and handled by it. As a result,      * parent ViewGroup won't receive the touch event any longer.      *      * We can't Intercept the touch event if we want to allow scrolling since ACTION_DOWN always      * happens before ACTION_MOVE.  So handle touch events here since onTouchEvent won't be triggered.      */     @Override     public boolean onInterceptTouchEvent(MotionEvent ev) {         mGestureDetector.onTouchEvent(ev);         if (ev.getAction() == MotionEvent.ACTION_UP && !mLongClicked)             this.callOnClick();         return false;     } } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!