ConstraintLayout上层布局点击触发下层视图响应问题求助
问题描述
我需要在全屏布局上方展示一个上层布局,但点击translationZ值更高的上层布局时,下层视图也会触发点击事件。希望下层视图可正常响应触摸手势,但点击上层布局时不触发下层的触摸事件。使用AppBarLayout时无此问题,但改用ConstraintLayout后无法解决该问题。
布局代码
<?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"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/clBigScreenPhotoInfo" android:layout_width="match_parent" android:layout_height="match_parent" android:translationZ="1dp" android:visibility="invisible"> <com.google.android.material.appbar.AppBarLayout android:background="#77000000" android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:elevation="0dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar_home" android:layout_width="match_parent" android:layout_height="72dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/ivBack" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_back_white" /> </androidx.constraintlayout.widget.ConstraintLayout> </com.google.android.material.appbar.AppBarLayout> <androidx.constraintlayout.widget.ConstraintLayout app:elevation="1dp" android:layout_width="match_parent" android:layout_height="120dp" android:background="#77000000" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent"> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout> <ImageView android:id="@+id/ivBig" android:translationZ="0dp" android:layout_width="match_parent" android:src="@drawable/big" android:layout_height="match_parent"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
下层ImageView点击监听器代码
binding.ivBig.setOnClickListener { val v = binding.clBigScreenPhotoInfo if (v.visibility == View.INVISIBLE) { v.visibility = View.VISIBLE return@setOnClickListener } v.visibility = View.INVISIBLE }
解决方案
问题根源是上层的clBigScreenPhotoInfo布局本身不消费触摸事件,导致事件会向下传递给下层的ImageView。以下两种方式可解决:
方法一:给上层布局设置空点击事件
给clBigScreenPhotoInfo添加点击监听器(空实现即可),让它主动消费触摸事件,阻止事件向下传递:binding.clBigScreenPhotoInfo.setOnClickListener { // 空实现,仅用于拦截触摸事件 }此方法不影响上层布局内子View(如返回按钮)的点击响应。
方法二:自定义触摸拦截布局
自定义ConstraintLayout并重写onTouchEvent方法,返回true表示消费所有触摸事件:class TouchBlockingConstraintLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) { override fun onTouchEvent(event: MotionEvent?): Boolean { return true // 消费触摸事件,不向下传递 } }然后在布局文件中替换原布局为自定义布局:
<com.yourpackage.TouchBlockingConstraintLayout android:id="@+id/clBigScreenPhotoInfo" android:layout_width="match_parent" android:layout_height="match_parent" android:translationZ="1dp" android:visibility="invisible"> <!-- 子布局保持不变 --> </com.yourpackage.TouchBlockingConstraintLayout>补充说明
之前用AppBarLayout无此问题,是因为AppBarLayout默认会处理触摸事件(如滑动手势),会主动消费事件;而普通ConstraintLayout默认不处理触摸事件,只要子View没拦截事件,就会继续向下传递。
内容的提问来源于stack exchange,提问作者kallis
相关产品推荐
相关产品推荐

