如何在ZoomageView上设置点击监听器并保留缩放功能
实现ZoomageView缩放与点击显示/隐藏底部导航栏的兼容方案
问题场景
用Kotlin开发Android图库应用,使用ZoomageView全屏展示图片,需求是点击图片时切换底部导航栏(含分享、收藏功能)的显示/隐藏,但遇到冲突:
- 给
Holder.itemView设置点击事件:图片可正常缩放,但底部导航栏无响应 - 给
sliderImageView(ZoomageView)设置点击事件:底部导航栏可切换显示/隐藏,但图片无法缩放
布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.jsibbold.zoomage.ZoomageView android:id="@+id/sliderImageView" android:layout_width="match_parent" android:layout_height="match_parent" app:zoomage_animateOnReset="true" app:zoomage_autoCenter="true" app:zoomage_autoResetMode="UNDER" app:zoomage_maxScale="8" app:zoomage_minScale="0.6" app:zoomage_restrictBounds="false" app:zoomage_translatable="true" app:zoomage_zoomable="true" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottomNavigationView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:visibility="gone" app:menu="@menu/bottom_navigation_menu" /> </LinearLayout>
Adapter原代码:
override fun onBindViewHolder(holder: ViewHolder, position: Int) { val photoPath: Uri = allImageList[position] val slideImageView: ImageView = holder.itemView.findViewById(R.id.sliderImageView) Glide.with(context).load(photoPath).into(slideImageView) var bottomNavigationView: BottomNavigationView = holder.itemView.findViewById(R.id.bottomNavigationView) // 允许缩放但不显示底部菜单 holder.itemView.setOnClickListener { bottomNavigationView.visibility = if (bottomNavigationView.visibility == View.VISIBLE) View.GONE else View.VISIBLE } // 显示底部菜单但无法缩放 slideImageView.setOnClickListener { bottomNavigationView.visibility = if (bottomNavigationView.visibility == View.VISIBLE) View.GONE else View.VISIBLE } }
解决思路
ZoomageView本身会处理缩放、平移的触摸事件,直接给它设置OnClickListener会覆盖其内部的手势处理,导致无法缩放;而给父布局itemView设置点击时,ZoomageView会消费触摸事件,导致父布局的点击事件无法触发。
正确做法是给ZoomageView添加触摸监听,通过判断触摸时长和移动距离识别单次点击,再触发底部导航栏的显示/隐藏,同时保留ZoomageView的原生缩放功能。
修改后的Adapter代码
override fun onBindViewHolder(holder: ViewHolder, position: Int) { val photoPath: Uri = allImageList[position] val slideImageView = holder.itemView.findViewById<com.jsibbold.zoomage.ZoomageView>(R.id.sliderImageView) Glide.with(context).load(photoPath).into(slideImageView) val bottomNavigationView = holder.itemView.findViewById<BottomNavigationView>(R.id.bottomNavigationView) // 用GestureDetector识别点击事件,不干扰ZoomageView的缩放 val gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() { override fun onSingleTapConfirmed(e: MotionEvent): Boolean { // 切换底部导航栏显示状态 bottomNavigationView.visibility = if (bottomNavigationView.visibility == View.VISIBLE) View.GONE else View.VISIBLE return true } }) // 给ZoomageView设置触摸监听,传递事件给GestureDetector slideImageView.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) // 返回false,让ZoomageView继续处理缩放等手势 false } }
代码说明
- 使用
GestureDetectorCompat的onSingleTapConfirmed方法识别可靠的单次点击,避免和缩放手势混淆 - 给ZoomageView设置
OnTouchListener,将触摸事件传递给GestureDetector后返回false,让ZoomageView继续处理自身的缩放、平移逻辑 - 移除原有的
itemView和slideImageView的OnClickListener,避免事件冲突
内容的提问来源于stack exchange,提问作者Iamvp
相关产品推荐
相关产品推荐

