文章目录
- [Android 扩大View的点击区域](#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>