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>
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo5 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077005 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼5 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone5 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui