我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么利用Android仿微博正文链接交互效果

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么利用Android仿微博正文链接交互效果

本篇内容主要讲解“怎么利用Android仿微博正文链接交互效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么利用Android仿微博正文链接交互效果”吧!

一、链接的匹配和显示交互

首先我们先分析一下链接的组成部分,可以肯定的是需要一个显示的标题,我们可能会对这个标题在UI表现上做些处理(常见的是一个链接的标志和设置不同的颜色)来提示和吸引用户的注意,另外还需要点击时跳转的链接,这条链接可以是内部也可以是外部(这就属于业务的需求)。关于链接的匹配方式可能会有不同的方案,我们这里选择了使用a标签的匹配方式,也就是接口会把链接的数据以a标签的形式给我们,客户端来进行匹配数据,下边我们简单的举一个例子,接口返回数据如下:

"你说的<a href="https://www.qq.com" rel="external nofollow"  rel="external nofollow" >我是链接</a>11111<a href="https://www.baidu.com" rel="external nofollow"  rel="external nofollow" >我也是链接</a>好开心啊,哈哈哈哈"

接下来我们对数据的处理:

suspend fun computeLenFilterLink(text: String, mContext: Context): SpannableStringBuilder =    withContext(Dispatchers.Default) {        var strings = SpannableStringBuilder(text)        val pattern = "<a \s*href\s*=\s*(?:.*?)>(.*?)</a\s*>"        val p = Pattern.compile(pattern)        val matcher = p.matcher(strings)        while (matcher.find()) {            val str = matcher.group()            val linkTitle = matcher.group(1) ?: ""            //a标签链接正则匹配            val patternUrlString =                "\s*(?i)href\s*=\s*("([^"]*")|'[^']*'|([^'">\s]+))"            val patternUrl = Pattern.compile(                patternUrlString,                Pattern.CASE_INSENSITIVE            )            //链接url            val matcherUrL = patternUrl.matcher(strings)            var linkUrl = ""            while (matcherUrL.find()) {                linkUrl = matcherUrL.group()                linkUrl = linkUrl.replace("href\s*=\s*(['|"]*)".toRegex(), "")                linkUrl = linkUrl.replace("['|"]".toRegex(), "")                linkUrl = linkUrl.trim { it <= ' ' }                break            }            //设置颜色            val sb = SpannableString("#$linkTitle")            sb.setSpan(                ForegroundColorSpan(                    ContextCompat.getColor(mContext, R.color.link_color)                ), 0,                sb.length,                Spanned.SPAN_INCLUSIVE_INCLUSIVE            )            sb.setSpan(                object : MyLinkClickSpan(mContext) {                    override fun onSpanClick(widget: View?) {                        //链接跳转                        Toast.makeText(mContext, "点击链=$linkUrl", Toast.LENGTH_SHORT).show()                    }                },                0, sb.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE            )            val start = strings.indexOf(str)            strings.delete(start, start + str.length)            //插入链接            strings.insert(start, sb)        }        return@withContext strings    }

这里我们是用正则匹配的方式取出链接的标题和跳转链接,然后设置链接的标志和颜色替换原来的a标签插入正文数据中。接下来就是设置显示的数据:

val string = "你说的<a href="https://www.qq.com" rel="external nofollow"  rel="external nofollow" >我是链接</a>11111<a href="https://www.baidu.com" rel="external nofollow"  rel="external nofollow" >我也是链接</a>好开心啊,哈哈哈哈"lifecycleScope.launch {    val contentString = LinkCheckHelper.computeLenFilterLink(string,this@MainActivity)    tvLink.text = contentString}

二、链接的点击交互

参考微博的交互效果我们会发现当我们触摸链接内容时其背景会由透明变为链接文字的颜色,手指抬起时又置回透明。细心的你肯定发现我们在刚才链接数据的插入时设置了MyLinkClickSpan做了对链接点击的处理,那么背景颜色的改变就要在ClickSpan中的 updateDrawState(ds: TextPaint)方法中进行处理,代码如下:

class MyLinkClickSpan(private val context: Context) :    ClickableSpan(), IPressedSpan {    private var isPressed = false    abstract fun onSpanClick(widget: View?)    override fun onClick(widget: View) {        if (ViewCompat.isAttachedToWindow(widget)) {            onSpanClick(widget)        }    }    override fun setPressed(pressed: Boolean) {        isPressed = pressed    }    override fun updateDrawState(ds: TextPaint) {        if (isPressed) {            ds.bgColor = ContextCompat.getColor(context, R.color.link_bg_color)        } else {            ds.bgColor = ContextCompat.getColor(context, android.R.color.transparent)        }        ds.isUnderlineText = false    }}

我们发现背景颜色的变化是需要对手指按下和抬起分别进行处理,所以这时不可避免的我们就要对触摸事件进行处理:

class LinkTextView(context: Context, attrs: AttributeSet?) :    AppCompatTextView(context, attrs) {    private var mPressedSpan: IPressedSpan? = null    init {        isFocusable = false        isLongClickable = false//        有链接点击需求不设置则点击无效        movementMethod = MyLinkMovementMethod.instance        highlightColor = Color.TRANSPARENT    }    override fun onTouchEvent(event: MotionEvent): Boolean {        val text = text        val spannable = Spannable.Factory.getInstance().newSpannable(text)        if (event.action == MotionEvent.ACTION_DOWN) {            //按下时记下clickSpan            mPressedSpan = getPressedSpan(this, spannable, event)        }        return if (mPressedSpan != null) {            //如果有clickSpan就走MyLinkMovementMethod的onTouchEvent            MyLinkMovementMethod.instance.onTouchEvent(this, getText() as Spannable, event)        } else {            super.onTouchEvent(event)        }    }    private fun getPressedSpan(        textView: TextView, spannable: Spannable,        event: MotionEvent    ): IPressedSpan? {        var mTouchSpan: IPressedSpan? = null        var x = event.x.toInt()        var y = event.y.toInt()        x -= textView.totalPaddingLeft        x += textView.scrollX        y -= textView.totalPaddingTop        y += textView.scrollY        val layout = textView.layout        val line = layout.getLineForVertical(y)        try {            var off = layout.getOffsetForHorizontal(line, x.toFloat())            if (x < layout.getLineLeft(line) || x > layout.getLineRight(line)) {                // 实际上没点到任何内容                off = -1            }            val linkSpans =                spannable.getSpans(off, off, IPressedSpan::class.java)            if (!linkSpans.isNullOrEmpty()) {                mTouchSpan = linkSpans[0]            }            return mTouchSpan        } catch (e: IndexOutOfBoundsException) {            Log.d(this.toString(), "getPressedSpan", e)        }        return null    }}
class MyLinkMovementMethod : LinkMovementMethod() {    override fun onTouchEvent(widget: TextView, buffer: Spannable, event: MotionEvent): Boolean {        return (sHelper.onTouchEvent(widget, buffer, event))    }    companion object {        val instance: MyLinkMovementMethod            get() {                if (sInstance == null) {                    sInstance = MyLinkMovementMethod()                }                return sInstance as MyLinkMovementMethod            }        private var sInstance: MyLinkMovementMethod? = null        private val sHelper = SpanClickHelper()    }}
class SpanClickHelper {    private var mPressedSpan: IPressedSpan? = null    fun onTouchEvent(        textView: TextView,        spannable: Spannable,        event: MotionEvent    ): Boolean {        return when (event.action) {            MotionEvent.ACTION_DOWN -> {                mPressedSpan = getPressedSpan(textView, spannable, event)                if (mPressedSpan != null) {                    //手指按下 设置按下为true,修改对应的链接文字背景颜色                    mPressedSpan!!.setPressed(true)                    //设置选中区域                    Selection.setSelection(                        spannable, spannable.getSpanStart(mPressedSpan),                        spannable.getSpanEnd(mPressedSpan)                    )                }                mPressedSpan != null            }            MotionEvent.ACTION_MOVE -> {                val touchedSpan = getPressedSpan(textView, spannable, event)                if (mPressedSpan != null && touchedSpan != mPressedSpan) {                    //手指移动时 设置按下为false,对应的链接文字背景颜色置回透明                    mPressedSpan!!.setPressed(false)                    mPressedSpan = null                    //移除选中区域                    Selection.removeSelection(spannable)                }                mPressedSpan != null            }            MotionEvent.ACTION_UP -> {                var touchSpanHint = false                if (mPressedSpan != null) {                    touchSpanHint = true                    //手指抬起时 设置按下为false,对应的链接文字背景颜色置回透明                    mPressedSpan!!.setPressed(false)                    //传递点击事件回调                    mPressedSpan!!.onClick(textView)                }                mPressedSpan = null                Selection.removeSelection(spannable)                touchSpanHint            }            else -> {                if (mPressedSpan != null) {                    //其它收拾 都设置按下为false,对应的链接文字背景颜色置回透明                    mPressedSpan!!.setPressed(false)                }                //移除选中区域                Selection.removeSelection(spannable)                false            }        }    }        private fun getPressedSpan(        textView: TextView,        spannable: Spannable,        event: MotionEvent    ): IPressedSpan? {        var x = event.x.toInt()        var y = event.y.toInt()        x -= textView.totalPaddingLeft        y -= textView.totalPaddingTop        x += textView.scrollX        y += textView.scrollY        val layout = textView.layout        val line = layout.getLineForVertical(y)        try {            var off = layout.getOffsetForHorizontal(line, x.toFloat())            if (x < layout.getLineLeft(line) || x > layout.getLineRight(line)) {                // 实际上没点到任何内容                off = -1            }            val link = spannable.getSpans(                off, off,                IPressedSpan::class.java            )            var touchedSpan: IPressedSpan? = null            if (link.isNotEmpty()) {                touchedSpan = link[0]            }            return touchedSpan        } catch (e: IndexOutOfBoundsException) {            Log.d(this.toString(), "getPressedSpan", e)        }        return null    }}

代码比较简单,就是对点击区域判断是否为链接,然后根据手势的操作分别设置给ClickSpan是否按下,来改变链接的背景颜色。

另外需要注意一点的是必须要调用下边的代码:

movementMethod = MyLinkMovementMethod.instance

此方法设置链接的点击。 另外,不同的机型上系统会有一个链接的高亮颜色,我们需要调用

highlightColor = Color.TRANSPARENT

来取消掉。

这样,链接的显示和点击交互就完成了。 具体效果:

怎么利用Android仿微博正文链接交互效果

到此,相信大家对“怎么利用Android仿微博正文链接交互效果”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么利用Android仿微博正文链接交互效果

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么利用Android仿微博正文链接交互效果

本篇内容主要讲解“怎么利用Android仿微博正文链接交互效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么利用Android仿微博正文链接交互效果”吧!一、链接的匹配和显示交互首先我们先分
2023-06-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录