Android 扩大View的点击区域

文章目录

Android 扩大View的点击区域

使用padding属性

通过设置 padding 属性扩大点击区域。

使用:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="hello" />

    <TextView
        android:id="@+id/text2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="40dp"
        android:text="world" />

</LinearLayout>

使用TouchDelegate

TouchDelegate 类是 Android 中的一个辅助类,可以用于扩展 View 的触摸区域,如小按钮。

  • 目标View必须有父 View。
  • 给多个 View 扩大点击区域时,不能是同一个父 View,从 View 类的源码中可知,设置 setTouchDelegate 时,会覆盖之前的。

扩展类:

kotlin 复制代码
fun View.expandTouchView(expandSize: Int = 15.dp) {
    val parentView = parent as? View
    parentView?.post {
        val rect = Rect()
        getHitRect(rect)
        Log.e("TAG", "rect = $rect")
        rect.left -= expandSize
        rect.top -= expandSize
        rect.right += expandSize
        rect.bottom += expandSize
        Log.e("TAG", "expandRect = $rect")
        parentView.touchDelegate = TouchDelegate(rect, this)
    }
}

使用:

kotlin 复制代码
val text1 = findViewById<TextView>(R.id.text1)
val text2 = findViewById<TextView>(R.id.text2)

text1.run {
    expandTouchView()
    setOnClickListener {
        ToastUtils.show((it as TextView).text.toString())
    }
}

text2.run {
    expandTouchView(40.dp)
    setOnClickListener {
        ToastUtils.show((it as TextView).text.toString())
    }
}

使用getLocationOnScreen监听

  • 使用 getLocationOnScreen() 可以获取目标 View 在屏幕中的坐标。
  • RectF 是一个用于表示浮点坐标的矩形区域的类,可以用于设置扩大区域。
  • 通过监听 onTouchEvent() 触摸方法获取触摸的坐标,然后判断是否在扩大区域内。

自定义View:

kotlin 复制代码
class ParentTouchView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    private lateinit var text1: TextView

    override fun onFinishInflate() {
        super.onFinishInflate()
        if (childCount > 0) {
            text1 = findViewById(R.id.text1)
            text1.setOnClickListener {
                ToastUtils.show(text1.text.toString())
            }
        }
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        event?.let { e ->
            if (e.action == MotionEvent.ACTION_DOWN) {
                if (isExpandView(text1, e.rawX, e.rawY, 100.dp)) {
                    text1.performClick()
                }
            }
        }
        return super.onTouchEvent(event)
    }

    /**
     * 是否在View的扩大区域
     *
     * @param targetView 目标View
     * @param touchX 点击的位置
     * @param touchY 点击的位置
     * @param expandSize 扩大区域的大小
     * @return
     */
    private fun isExpandView(
        targetView: View,
        touchX: Float,
        touchY: Float,
        expandSize: Int = 15.dp
    ): Boolean {
        // 获取目标View的Rect
        val rect = RectF()
        val location = IntArray(2)
        // 获取目标View的坐标
        targetView.getLocationOnScreen(location)
        val childX = location[0].toFloat()
        val childY = location[1].toFloat()
        rect.set(
            childX,
            childY,
            childX + targetView.width,
            childY + targetView.height
        )

        // 设置扩大区域后的Rect
        rect.apply {
            left -= expandSize
            top -= expandSize
            right += expandSize
            bottom += expandSize
        }

        // 判断是否在扩大区域内
        return rect.contains(touchX, touchY)
    }
}

使用:

kotlin 复制代码
<?xml version="1.0" encoding="utf-8"?>
<com.example.xxx.view.ParentTouchView 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".clickarea.LocationOnScreenActivity">

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello" />

</com.example.xxx.view.ParentTouchView>
相关推荐
黄林晴2 小时前
如何判断手机是否是纯血鸿蒙系统
android
火柴就是我2 小时前
flutter 之真手势冲突处理
android·flutter
法的空间3 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
循环不息优化不止3 小时前
深入解析安卓 Handle 机制
android
恋猫de小郭3 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
jctech3 小时前
这才是2025年的插件化!ComboLite 2.0:为Compose开发者带来极致“爽”感
android·开源
用户2018792831673 小时前
为何Handler的postDelayed不适合精准定时任务?
android
叽哥4 小时前
Kotlin学习第 8 课:Kotlin 进阶特性:简化代码与提升效率
android·java·kotlin
Cui晨4 小时前
Android RecyclerView展示List<View> Adapter的数据源使用View
android
氦客4 小时前
Android Doze低电耗休眠模式 与 WorkManager
android·suspend·休眠模式·workmanager·doze·低功耗模式·state_doze