zoukankan      html  css  js  c++  java
  • TextView之富文本

    项目中使用富文本比较常见了,一行显示多种样式颜色的文本,使用 ClickableSpan 富文本实现在同一个 TextView 中的文本的颜色、大小、背景色等属性的多样化和个性化。

    我们也可以使用Html.fromHtml(string)来编写文本格式,需要注意
    1.当string过大,会抛出IOException
    2.Html.fromHtml(string)会将string中的’ ’和’ ’替换成空格,因此我们需要显式的将其替换为html可以识别的’<br>’否则会报IOException
    3.android原生仅支持部分html tag标签
     

    使用ClickableSpan会遇到的问题

    用ClickableSpan给TextView中文本设置响应事件,再对TextView设置响应事件,点击ClickableSpan时,会同时触发2个事件。
    常见案例:评论回复,点击文本,弹出对话框,点击昵称,进入用户主页(朋友圈评论回复)
    原因:
    1.查看源码得知,给TextView setMovementMethod中,LinkMovementMethod的onTouchEvent方法,会同时触发自身的onClick事件 ,返回给view进行处理,这时该TextView也消耗了事件,因此会触发2个事件。
    2. TextView setMovementMethod方法,默认将以下3个方法设置为true,根据安卓的事件分发机制,TextView也会消耗掉该事件。
    setFocusable(true); setClickable(true); setLongClickable(true);

    如何解决:

    上述例子中,我们可以禁用TextView的点击事件,点击文本时,交给父类去处理,点击昵称,ClickableSpan进入用户主页
    1. 重写LinkMovementMethod,将onTouchEvent事件返回为false.
    2.TextView不可点击。
    setFocusable(false);
    setClickable(false);
    setLongClickable(false);
     
     
    问题代码

     点击ClickableSpan,日志输出:

    修改后代码:

    ClickableMovementMethod修改:

    class ClickableMovementMethod : LinkMovementMethod() {
    
        companion object {
            val mInstance by lazy(LazyThreadSafetyMode.NONE){
                ClickableMovementMethod()
            }
    
        }
    
        override fun onTouchEvent(widget: TextView, buffer: Spannable, event: MotionEvent): Boolean {
            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 links = buffer.getSpans(off, off, ClickableSpan::class.java)
    
                if (links.size != 0) {
                    val link = links[0]
                    if (action == MotionEvent.ACTION_UP) {
                        link.onClick(widget)
                    } else if (action == MotionEvent.ACTION_DOWN) {
    
                        Selection.setSelection(
                            buffer,
                            buffer.getSpanStart(link),
                            buffer.getSpanEnd(link)
                        )
                    }
                    return true
                } else {
                    Selection.removeSelection(buffer)
                }
            }
            return false
        }
    
    
    }
    View Code
     
    日志输出:
     点击ClickableSpan:

    点击文本:

    参考链接:
  • 相关阅读:
    LeetCode 811. Subdomain Visit Count (子域名访问计数)
    LeetCode 884. Uncommon Words from Two Sentences (两句话中的不常见单词)
    LeetCode 939. Minimum Area Rectangle (最小面积矩形)
    LeetCode 781. Rabbits in Forest (森林中的兔子)
    LeetCode 739. Daily Temperatures (每日温度)
    三种方式实现按钮的点击事件
    239. Sliding Window Maximum
    14.TCP的坚持定时器和保活定时器
    13.TCP的超时与重传
    12.TCP的成块数据流
  • 原文地址:https://www.cnblogs.com/fangg/p/12752623.html
Copyright © 2011-2022 走看看