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:

    点击文本:

    参考链接:
  • 相关阅读:
    C/C++
    不使用判断语句求一组数中的奇数/偶数个数
    heap(堆)
    One-Hot Encoding(独热编码)
    泰坦尼克号生存预测
    LaTeX 使用笔记
    python学习 —— seaborn、matplotlib、pandas、numpy package的混合使用
    Python 读取本地*.txt文件 替换 内容 并保存
    MySQL基本命令脚本
    MySQL简介
  • 原文地址:https://www.cnblogs.com/fangg/p/12752623.html
Copyright © 2011-2022 走看看