1

I have an onclicklistener on a layout, which contains two includes. One of the includes contains a constraint layout which will be made visible on click of the container. It should also be made invisible again, if I click on the layout again. It works, if I click in the part that was always visible. However, if I click in the area of the newly added constraint layout, nothing happens. The onclick-listener does not fire. It works anywhere around the include though. E.g. clicking on the left of it (left there's a margin in original) it closes again. Here are the (simplified) layouts:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto"
    xmlns:card_view="http://schemas.android.com/apk/res-auto">

    <data>
      //Viewmodel
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{() -> viewModel.onClickItemContainer()}"
            android:clickable="true">

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
              >
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:animateLayoutChanges="true">

                    <include
                        android:id="@+id/item_main"
                        layout="@layout/item_always_visible"
                        bind:viewModel="@{viewModel}"
                        bind:layout_constraintTop_toTopOf="parent"
                        bind:layout_constraintStart_toStartOf="parent"/>

                    <include
                        layout="@layout/item_details"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        bind:viewModel="@{viewModel}"
                        bind:layout_constraintTop_toBottomOf="@id/item_main"
                        bind:layout_constraintStart_toStartOf="parent" />
                </androidx.constraintlayout.widget.ConstraintLayout>
            </androidx.cardview.widget.CardView>

        </FrameLayout>

    </LinearLayout>

</layout>

Included layout (that toggles on/off):

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        //Viewmodel
        <import type="android.view.View" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/entry_details"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="@{viewModel.detailsVisible? View.VISIBLE : View.GONE}"
        tools:visibility="visible"
        android:clickable="false">

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:adapter="@{viewModel.adapter}"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:clickable="false"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

I've tried around with clickable="false" in a couple of places in the included layout already, because I found that suggestion in another question, but it did not help anything. If it was affecting the whole extended area (also cardview below include, e.g) I'd be thinking it's a bug with Android not adapting click areas to layout changes, but since I can trigger the listener by clicking on left and below included part, it must be something else.

The items used in the recyclerview are also set to clickable = "false":

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
    </data>
    <TextView
        android:id="@+id/detail_text"
        xmlns:android="http://schemas.android.com/apk/res/android"
        style="@style/Text.SecondaryText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"/>
</layout>
  • Instead of using the "android:onClick" in the XML layout, did you try adding the listener programatically (in code)? – David Wasser Jul 31 '23 at 10:50
  • Your included layout is just a `ConstraintView` where you have `android:clickable="false"` that contains a `RecyclerView`. Clicking anywhere in the `RecyclerView` is going to generate a click event on the row of the `RecyclerView` and be routed there. Looks like you have an architectural/design conflict. – David Wasser Jul 31 '23 at 10:58
  • @DavidWasser The rows are clickable=false as well for that very reason. – Sarah Multitasker Jul 31 '23 at 11:39
  • Use the Layout Inspector to make sure that you understand everything that is in the view hierarchy. It is possible that there is a view in there that is capturing the clicks that you are not aware of. You can also just use [onInterceptTouchEvent()](https://developer.android.com/develop/ui/views/touch-and-input/gestures/viewgroup#intercept) in the _FrameLayout_ to intercept all touch events and avoid the complications of suppressing clicks on descendants. – Cheticamp Jul 31 '23 at 13:50
  • @Cheticamp Checked out LayoutInspector. No unexpected views in hierarchy. All views in that area resolve to clickable=false. Can't change to onInterceptTouchEvent, because there are also buttons contained in the always visible part that should not be intercepted. – Sarah Multitasker Jul 31 '23 at 14:30
  • Too bad. You can also used a hook into ` onInterceptTouchEvent()` to track a touch event through the view hierarchy to see where the failure is. If you truly suspect an Android bug with included views, as a test, you can just place the included not-always-visible view directly into the top-level layout and make it always visible to see if the problem persists. – Cheticamp Jul 31 '23 at 14:41

1 Answers1

1

Apparently that is a known issue with recyclerviews, that they catch the click event, because they use it for scrolling. A number of solutions can be found here: Parent click event not firing when recyclerview clicked In my case, making the recyclerview untouchable is a reasonable approach, because all elements are already in another recyclerview, so they will never get chopped and instead fill out the space required.