• 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:

    点击文本:

    参考链接:
  • 相关阅读:
    arm SecurCore 处理器【转】
    ARM内核全解析,从ARM7,ARM9到Cortex-A7,A8,A9,A12,A15到Cortex-A53,A57【转】
    arm处理器中a5 a8 a9,v6 v7,arm7 arm9 arm11都是依据什么来分类的【转】
    platform型设备在/dev目录下自动创建设备节点的分析【转】
    linux下bus、devices和platform的基础模型 【转】
    kernel 中 sscanf和sprintf()函数使用说明【转】
    Linux内核中的printf实现【转】
    sprintf,snprintf的用法(可以作为linux中itoa函数的补充)【转】
    Linux设备模型(3)_Uevent【转】
    Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】
  • 原文地址:https://www.cnblogs.com/fangg/p/12752623.html
Copyright © 2020-2023  润新知