点击区域扩大仅作用于最后一个View,如何实现全量生效?
问题根源
每个按钮调用increaseHitArea()时,都会直接给父View设置新的TouchDelegate,后设置的会完全覆盖之前的,所以只有最后一次调用的按钮能生效。
解决方案
核心思路是让父View的TouchDelegate同时管理多个按钮的扩大点击区域,而不是每次替换掉。
1. 自定义支持多区域的CompositeTouchDelegate
先创建一个能处理多个触摸委托的类:
class CompositeTouchDelegate(private val delegates: MutableList<TouchDelegate>) : TouchDelegate(Rect(), View(Context())) { override fun onTouchEvent(event: MotionEvent): Boolean { var isHandled = false // 遍历所有委托,处理触摸事件 delegates.forEach { delegate -> if (delegate.onTouchEvent(event)) { isHandled = true } } return isHandled } }
2. 修改扩展函数支持批量处理
把原来的单个View扩展函数改成批量处理多个View的版本:
fun List<View>.increaseHitArea(expandSize: Int = 50) { if (isEmpty()) return val parent = first().parent as View parent.doOnLayout { val touchDelegates = mutableListOf<TouchDelegate>() this.forEach { view -> val rect = Rect() view.getHitRect(rect) // 扩大点击区域 rect.top -= expandSize rect.left -= expandSize rect.bottom += expandSize rect.right += expandSize touchDelegates.add(TouchDelegate(rect, view)) } // 设置组合触摸委托 parent.touchDelegate = CompositeTouchDelegate(touchDelegates) } }
3. 调用方式
现在可以一次性给所有按钮设置扩大点击区域:
listOf(binding.button1, binding.button2, binding.button3).increaseHitArea()
可选:保留单个View调用的方式
如果需要保留单个View调用的能力,可以修改扩展函数,每次添加新的委托到组合中:
fun View.increaseHitArea(expandSize: Int = 50) { val parent = parent as View parent.doOnLayout { val rect = Rect() getHitRect(rect) rect.top -= expandSize rect.left -= expandSize rect.bottom += expandSize rect.right += expandSize val newDelegate = TouchDelegate(rect, this) // 处理已有委托,合并新委托 val existingDelegate = parent.touchDelegate parent.touchDelegate = when (existingDelegate) { is CompositeTouchDelegate -> { existingDelegate.delegates.add(newDelegate) existingDelegate } null -> { CompositeTouchDelegate(mutableListOf(newDelegate)) } else -> { CompositeTouchDelegate(mutableListOf(existingDelegate, newDelegate)) } } } }
这样原来的单个调用方式也能正常工作,多个按钮调用不会互相覆盖。
内容的提问来源于stack exchange,提问作者Ahmad Albatsh
相关产品推荐
相关产品推荐

