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

    点击文本:

    参考链接:
  • 相关阅读:
    关于管理单元初始化失败的解决方法
    如何快速在两台电脑之间传输大文件
    拿到商标受理通知书就可以打上“TM”就可以使用吗?
    山里王土蜂蜜
    我的博客今天1岁344天了,我领取了新锐博主徽章
    Winxp Stop c0000218 unknown hard error
    设置网易博客、新浪博客、博客园的windows live writer帐户支持
    邮件变成了Winmail.dat
    outlook 2007 .pst文件过大,提示:“磁盘空间已满,无法删除邮件”
    git 本地给远程仓库创建分支 三步法
  • 原文地址:https://www.cnblogs.com/fangg/p/12752623.html
Copyright © 2020-2023  润新知