简介
从您的问题看来,您想要实现的目标如下:
- 如果您的
TextView 是 textSelectable 则单击它应委托给 linear_layout。
- 长按或双击仍应由
TextView 处理
可能的解决方案
为什么不将您的自定义textGestureDetector 递归地设置为每个后代TextView?在这种情况下,您不需要为每个孩子/后代 TextView 手动执行此操作。
首先,将onSingleTapConfirmed 中的事件委托给linear_layout,如下所示:
val textGestureDetector = GestureDetectorCompat(context, GestureDetector.SimpleOnGestureListener())
textGestureDetector.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener {
override fun onDoubleTap(e: MotionEvent?): Boolean = false
override fun onDoubleTapEvent(e: MotionEvent?): Boolean = false
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
// pass the click event to your linear_layout
linearLayout.performClick()
return true
}
})
然后,将您的OnClickListener 添加到linear_layout,如下所示:
linear_layout.setOnClickListener {
Toast.makeText(context,"click just happened",Toast.LENGTH_LONG).show()
}
最后,调用initTextViewSingleTapListener(这会将您的自定义onTapListener 设置为每个TextView,它是linear_layout 的后代)
initTextViewSingleTapListener(linear_layout, linear_layout, textGestureDetector)
可以这样实现:
fun initTextViewSingleTapListener(root: ViewGroup, currentView: View, textGestureDetector: GestureDetectorCompat) {
if (currentView is TextView) {
currentView.setOnTouchListener { _, event ->
textGestureDetector.onTouchEvent(event)
false
}
return
}
if (currentView is ViewGroup) {
for (i in 0..currentView.childCount) {
val child = currentView.getChildAt(i)
if (child != null) {
initTextViewSingleTapListener(root, child, textGestureDetector)
}
}
}
}
如果您的TextView 已经有一个侦听器,因此您不想替换它,那么只需在添加您的侦听器之前添加!currentView.hasOnClickListeners() 之类的检查:
...
if (!currentView.hasOnClickListeners()) {
currentView.setOnTouchListener { _, event ->
textGestureDetector.onTouchEvent(event)
false
}
}
...
完整代码
请在下面找到完整的示例代码:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val textGestureDetector = GestureDetectorCompat(context, GestureDetector.SimpleOnGestureListener())
textGestureDetector.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener {
override fun onDoubleTap(e: MotionEvent?): Boolean = false
override fun onDoubleTapEvent(e: MotionEvent?): Boolean = false
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
// pass the click event to the linear layout
linear_layout.performClick()
return true
}
})
linear_layout.setOnClickListener {
Toast.makeText(context,"click just happened",Toast.LENGTH_LONG).show()
}
initTextViewSingleTapListener(linear_layout, linear_layout, textGestureDetector)
}
fun initTextViewSingleTapListener(root: ViewGroup, currentView: View, textGestureDetector: GestureDetectorCompat) {
if (currentView is TextView) {
if (currentView.hasOnClickListeners()) {
// do nothing since your View already has a click listener on it.
return
}
currentView.setOnTouchListener { _, event ->
textGestureDetector.onTouchEvent(event)
false
}
return
}
if (currentView is ViewGroup) {
for (i in 0..currentView.childCount) {
val child = currentView.getChildAt(i)
if (child != null) {
initTextViewSingleTapListener(root, child, textGestureDetector)
}
}
}
}
更新
由于您的问题要求已更改,因此我在此处添加额外说明。
如果 textSelectable TextView 应该将单击事件委托给其最近的 ViewGroup 祖先,那么在您的 initTextViewSingleTapListener()'s 块中如下所示:
if (currentView is ViewGroup) {
for (i in 0..currentView.childCount) {
val child = currentView.getChildAt(i)
if (child != null) {
initTextViewSingleTapListener(root, child, textGestureDetector)
}
}
}
将root 替换为currentView,以便将所有单击事件委托给最近的ViewGroup 祖先:
...
initTextViewSingleTapListener(currentView, child, textGestureDetector)
...