iOS-文本内容展开/收起实现方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS-文本内容展开/收起实现方案相关的知识,希望对你有一定的参考价值。

参考技术A 问题:YYLabel继承于UIView不支持项目本身的自定义表情,UILabel能正常显示自定义表情,pass

思路:手动获取label的显示字符个数,自己处理展示逻辑+点击逻辑

手动获取label的显示字符个数

1.用UITextView的链接,有点瑕疵。
具体为:点击一下会出现灰色背景色,长按会出现一个菜单,还有剪切复制菜单。

txtView.isSelectable = false // 同时禁用了可选和超链接跳转
canPerformAction return false // 不显示菜单栏了,但是仍然可选
添加长按手势以屏蔽默认的手势 // 不能屏蔽
添加自定义手势,并禁用掉其他手势 // do work

2.用CoreText的点击
瑕疵:
展开文案没有完全居右
收起的点击区域不太准确
带表情的多行文本展示了2行

3.保底方案
另起一行展开/收起,不追加在内容后面。
遇到问题:展开收起-tabview闪动
禁用掉预估高度,然后手动计算cell高度即可

1、let line: CTLineRef = CFArrayGetValueAtIndex(lines, 0)
这会产生错误“’ConstUnsafePointer<()&'不能转换为'CTLineRef''. Cast似乎没有改变这个错误
let line: CTLineRef = lines[0]
产生错误“’CFArrayRef’没有名为’subscript’的成员”
改用unsafeBitCast即可
Swift 类型UnsafeRawPointer转化报错

2、ios获取UILabel每行显示的文字
https://www.jianshu.com/p/65a07b6013c7

3、iOS 富文本添加点击事件
https://www.jianshu.com/p/480db0cc7380

4、iOS中CoreText框架探究
https://www.jianshu.com/p/9987e6194b2e

5、展开收起-tabview闪动
禁用掉预估高度,然后手动计算cell高度即可

Android 支持展开收起的TextView

✏️ 丨 Android 支持展开收起的TextView

1. 需求如下:

近期需要做一个长文本展开收起的功能,当文本内容超过两行,显示展示按钮,点击展开按钮显示全部内容,当文本内容未超过两行时,不显示展示按钮。

2. 实现效果展示

3. 封装的工具类

/**
 * Desc 支持展开收起的TextView
 * Author ZY
 * Date 2021/10/10 10:30
 */
class ExpandTextView(var context: Context) 

    // 默认展示行数,超过多少行隐藏
    private var maxLine: Int = 2

    // 文本左右边距总合
    private var margin: Int = 0

    // 展开、收起文本颜色
    private var colorStr: String = "#0079e2"

    // 展开显示文本
    private var expandStr: String = "展开"

    // 收起显示文本
    private var foldStr: String = "收起"

    fun setMaxLine(maxLine: Int): ExpandTextView 
        this.maxLine = maxLine
        return this
    

    fun setMargin(margin: Int): ExpandTextView 
        this.margin = margin
        return this
    

    fun setColorStr(colorStr: String): ExpandTextView 
        this.colorStr = colorStr
        return this
    

    fun setFoldStr(foldStr: String): ExpandTextView 
        this.foldStr = foldStr
        return this
    

    fun setExpandStr(expandStr: String): ExpandTextView 
        this.expandStr = expandStr
        return this
    

    fun show(expandTextView: TextView, content: String) 

        // 裁剪函数来去除前导空格
        expandTextView.text = content.trimIndent()

        // 获取TextView的画笔对象
        val paint = expandTextView.paint

        // 每行文本布局宽度: 屏幕宽度 - 左右边距
        val width = context.resources.displayMetrics.widthPixels - context.resources.getDimension(margin).toInt()

        val fontColor = ForegroundColorSpan(Color.parseColor(colorStr))
        // 实例化StaticLayout
        val staticLayout = StaticLayout(content, paint, width, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false)
        // 判断content行数是否超过最大限制行数
        if (staticLayout.lineCount > maxLine) 
            /**
             * 展开后的文本内容
             */
            val str = ("$content\\t\\t$foldStr")
            val expandSpanStr = SpannableString(str)
            expandSpanStr.setSpan(fontColor, str.length - 2, str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            //获取最后一个文字的下标
            val index = staticLayout.getLineStart(maxLine) - 1

            /**
             * 收起后的文本内容
             */
            val str2 = ("$content.substring(0, index - 2)...$expandStr")
            val foldSpanStr = SpannableString(str2)
            foldSpanStr.setSpan(fontColor, str2.length - 2, str2.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            //设置收起后的文本内容
            expandTextView.text = foldSpanStr
            expandTextView.setOnClickListener 
                if (expandTextView.isSelected)  //收起的状态
                    expandTextView.text = expandSpanStr
                    expandTextView.isSelected = false
                 else  //展开的状态
                    expandTextView.text = foldSpanStr
                    expandTextView.isSelected = true
                
            
            //设成选中状态 true收起状态,false展示状态
            expandTextView.isSelected = true
         else 
            //未超过最大限制行数,直接设置文本
            expandTextView.text = content
            expandTextView.setOnClickListener(null)
        
    

4. 调用方式如下

采用链式调用方式,可动态配置默认显示行数、提示文字颜色、边距

     override fun onCreate(savedInstanceState: Bundle?) 
        val content = "日前,河南郑州市金水区税务局运用大数据实现信息系统自动提取数据,加大文娱领域从业人员税收征管力度,追征一名网红的662.44万元税款收入国库。笔者看来,网红补税释放了两个信号。一是新技术会更多应用在税收征管中,实现应缴尽缴。二是某些领域行业还存在税收征管盲区,需要加大征管力度。加大对明星、网红的税收征管力度,是国家加大对高收入群体税收监管力度的一个缩影,这一举措有助于税负公平,有利于调节收入分配,促进社会公平。社会公众关注高收入群体缴税情况,也是追求责任义务对等公平的体现。"
        val ex  = ExpandTextView(this)
            .setMaxLine(2)
            .setMargin(R.dimen.dp_60)
            .setColorStr("#346CE9")
            .setFoldStr("查看全部")
            .setExpandStr("展开")
			.show(tv_remark, content)

如果显示多个展开收起组件,可以复用设置的属性

     override fun onCreate(savedInstanceState: Bundle?) 

		// 情景一:文本长度超过两行
        val content = "日前,河南郑州市金水区税务局运用大数据实现信息系统自动提取数据,加大文娱领域从业人员税收征管力度,追征一名网红的662.44万元税款收入国库。笔者看来,网红补税释放了两个信号。一是新技术会更多应用在税收征管中,实现应缴尽缴。二是某些领域行业还存在税收征管盲区,需要加大征管力度。加大对明星、网红的税收征管力度,是国家加大对高收入群体税收监管力度的一个缩影,这一举措有助于税负公平,有利于调节收入分配,促进社会公平。社会公众关注高收入群体缴税情况,也是追求责任义务对等公平的体现。"

		// 情景二:当文本长度不足两行
        val content2 = "情景二:当文本长度不足两行:"

        val content3 ="据公开消息,北方多地经历暴雪、降温。进入11月份,全省供暖工作陆续启动,为此,沈阳局集团公司充分发挥煤炭运输主通道作用,以保发电供热用煤为重点。值得注意的是,今年以来国际市场能源价格大幅上涨,国内电力、煤炭供需持续偏紧,大家都担心煤电供应问题。"

        val ex  = ExpandTextView(this)
            .setMaxLine(2)
            .setMargin(R.dimen.dp_60)
            .setColorStr("#346CE9")

        ex.show(tv_remark, content)
        ex.show(tv_remark2, content2)
        ex.show(tv_remark3, content3)

以上是关于iOS-文本内容展开/收起实现方案的主要内容,如果未能解决你的问题,请参考以下文章

CSS 实现多行文本“展开收起”

Android 支持展开收起的TextView

Android 支持展开收起的TextView

Android 支持展开收起的TextView

Android 支持展开收起的TextView

VUE transition实现展开/收起高度不确定的元素