Skip to content

Instantly share code, notes, and snippets.

@dyguests
Created November 7, 2018 02:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dyguests/ce7135522e000dba30ac8b33ed8e4aff to your computer and use it in GitHub Desktop.
Save dyguests/ce7135522e000dba30ac8b33ed8e4aff to your computer and use it in GitHub Desktop.
使 TextView 的 ClickSpan 可以响应,但是不影响 原TextView其它区域的点击处理,防止父控件无响应
import android.text.Selection
import android.text.Spannable
import android.text.Spanned
import android.text.method.BaseMovementMethod
import android.text.style.ClickableSpan
import android.view.MotionEvent
import android.view.View
import android.widget.TextView
/**
* see [https://blog.csdn.net/zhaizu/article/details/51038113]
*
* 使用方法:
*
* // more code
* TextView content = new TextView(getContext());
* // more code
* content.setMovementMethod(ClickableMovementMethod.getInstance());
* content.setOnTouchListener(ClickableMovementMethod.getInstance());
* content.setFocusable(false);
* content.setClickable(false);
* content.setLongClickable(false);
* ---------------------
* 作者:zhaizu
* 来源:CSDN
* 原文:https://blog.csdn.net/zhaizu/article/details/51038113
* 版权声明:本文为博主原创文章,转载请附上博文链接!
*/
internal class ClickableMovementMethod : BaseMovementMethod(), View.OnTouchListener {
override fun onTouchEvent(widget: TextView, buffer: Spannable, event: MotionEvent): Boolean {
val action = event.actionMasked
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
var x = event.x.toInt()
var y = event.y.toInt()
x -= widget.totalPaddingLeft
y -= widget.totalPaddingTop
x += widget.scrollX
y += widget.scrollY
val layout = widget.layout
val line = layout.getLineForVertical(y)
val off = layout.getOffsetForHorizontal(line, x.toFloat())
val link = buffer.getSpans(off, off, ClickableSpan::class.java)
if (link.size > 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget)
} else {
Selection.setSelection(
buffer, buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0])
)
}
return true
} else {
Selection.removeSelection(buffer)
}
}
return false
}
override fun onTouch(v: View, event: MotionEvent): Boolean {
val widget = v as TextView
val text = widget.text
if (text is Spanned) {
val action = event.action
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
var x = event.x.toInt()
var y = event.y.toInt()
x -= widget.totalPaddingLeft
y -= widget.totalPaddingTop
x += widget.scrollX
y += widget.scrollY
val layout = widget.layout
val line = layout.getLineForVertical(y)
val off = layout.getOffsetForHorizontal(line, x.toFloat())
val link = text.getSpans(
off, off,
ClickableSpan::class.java
)
if (link.size != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget)
} else if (action == MotionEvent.ACTION_DOWN) {
// Selection only works on Spannable text. In our case setSelection doesn't work on spanned text
// Selection.setSelection((Spannable) buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
}
return true
}
}
}
return false
}
override fun initialize(widget: TextView, text: Spannable) {
Selection.removeSelection(text)
}
companion object {
private var sInstance: ClickableMovementMethod? = null
val instance: ClickableMovementMethod
get() {
if (sInstance == null) {
sInstance = ClickableMovementMethod()
}
return sInstance!!
}
/**
* 使 TextView 的 ClickSpan 可以响应,但是不影响 原TextView其它区域的点击处理,防止父控件无响应
*/
fun setupTextView(textView: TextView) {
textView.apply {
movementMethod = ClickableMovementMethod.instance
setOnTouchListener(ClickableMovementMethod.instance)
isFocusable = false
isClickable = false
isLongClickable = false
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment