1

I have a Recyclerview that contains CardViews. The CardViews contain a ViewPager2 and a few other views (text, etc). I want to capture when a user clicks anywhere on the CardView (the parent) and run some logic. The problem: even though the ViewPager is a child of the CardView, it still interferes with the CardView's onClickListener and if the user clicks on the portion of the CardView where the ViewPager is drawn the CardView's listener is never triggered.

This is interesting fundamentally because I would expect the parent view to supersede any click listeners in the children, but the ViewPager seems to be a unique layout in this regard.

I've looked into solutions here but i'm not sure if any of them are the best practice since this onClick logic resides in a RecyclerView in my case. Since i'm instantiating the listener in my ViewHolder's init method it should be avoiding unnecessary object instantiation but i'm cautious not to make an inefficient solution.

The requirements for my solution are:

  1. If a user clicks anywhere on my CardView, run my onClickListener (which'll launch a fragment)
  2. If a user swipes the ViewPager within my CardView, let the ViewPager handle the event as usual and don't run the CardView's onClick logic

What's the proper way to do this? With my code below, clicks outside of the ViewPager are working but clicks on top of the ViewPager don't trigger my fragment-launching logic.

ViewHolder

class RaffleViewHolder(cardView: CardView) : RecyclerView.ViewHolder(cardView), View.OnClickListener {
        val itemName = cardView.itemName
        val viewPager = cardView.viewPager
        val featuredWedge = cardView.quarter_circle
        val imageViewPagerAdapter = RaffleItemViewPagerAdapter()

        init {
            viewPager.adapter = imageViewPagerAdapter
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                viewPager.setPageTransformer(ViewPagerDepthPageTransformer())
            }
            cardView.setOnClickListener(this)
        }

        override fun onClick(view: View?) {
            Timber.d("onclick fired in recyclerviewadapter")
            //do stuff. This is only reached for clicks outside of the ViewPager
        }
    }

XML for CardView

<androidx.cardview.widget.CardView
    android:id="@+id/itemCard"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="2dp"
    android:elevation="2dp"
    app:cardBackgroundColor="@color/white">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_width="300dp"
            android:layout_height="300dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/itemName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/viewPager" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Cody
  • 1,801
  • 3
  • 28
  • 53

0 Answers0