Android TextView 在最后一行末尾加图标

news2024/11/23 11:11:30
当前有个需求.显示一段文本,文本最多显示两行,点击展开后才显示完全。当没有显示完全的时候,需要在文本的第二行末尾显示图标,点击图标和文本,文本展开。

  难点在于图标需要和第二行文本显示在同一行,高度和文本一致,居中显示。看似简单  实则思路不好想。最后搞了两天,用html富文本解决。

当中涉及到英文换行的坑  然后涉及到汉字全角  半角导致布局问题的坑。

代码如下

布局文件:

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_margin="10dp"
    android:layout_height="match_parent"
    android:maxLines="2"
    android:ellipsize="end"
    android:breakStrategy="balanced"
    />

Activity如下

package com.example.myapplication;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Html;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private String str = "我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱";

    private boolean isDeal = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.textView);
        textView.setText(toDBC(str));
        dealStr(textView);
    }

    public static String toDBC(String input) {
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == 12288) {
                // 全角空格为12288,半角空格为32
                c[i] = (char) 32;
                continue;
            }
            if (c[i] > 65280 && c[i] < 65375)
                // 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
                c[i] = (char) (c[i] - 65248);
        }
        return new String(c);
    }


    private void dealStr(TextView textView) {
        // 在TextView绘制完成后获取省略的字符数
        ViewTreeObserver vto = textView.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
               textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                if (isDeal) {
                    return;
                }
                isDeal = true;
              

                int ellipsisCount = 0;
                Layout layout = textView.getLayout();
                if (layout != null) {
                    int lineCount = layout.getLineCount();
                    if (lineCount > 0) {
                        int lastLineIndex = lineCount - 1;
                        // 输出省略的字符数
                        ellipsisCount = layout.getEllipsisCount(lastLineIndex);
                    }
                }

                // 获取文本内容
                CharSequence fullText = textView.getText();


                if (ellipsisCount > 0) {
                    // 截断发生
                    // 获取截断后的文本
                    CharSequence truncatedText = fullText.subSequence(fullText.length() - ellipsisCount, fullText.length());
                    CharSequence un_truncatedText = fullText.subSequence(0, fullText.length() - ellipsisCount);
                    String truncatedString = truncatedText.toString();
                    replaceStr(textView, un_truncatedText.toString());


                } else {
                    // 没有截断发生
                    replaceStr(textView, textView.getText().toString());
                }

            }
        });
    }


    private void replaceStr(TextView textView, String tex) {
        SpannableStringBuilder builder = new SpannableStringBuilder();
        // 添加HTML文本内容
        String htmlText = "<html><body>" + tex + "</body></html>";
        builder.append(Html.fromHtml(htmlText));
        // 获取Drawable图标
        Drawable icon = getResources().getDrawable(R.drawable.expand_icon);
        icon.setBounds((int) textView.getTextSize(), 0, icon.getIntrinsicWidth() + (int) textView.getTextSize(), icon.getIntrinsicHeight());
        // 创建一个ImageSpan来显示图标
        ImageSpan iconSpan = new ImageSpan(icon, ImageSpan.ALIGN_CENTER);
        // 将ImageSpan添加到SpannableStringBuilder的末尾
        builder.setSpan(iconSpan, builder.length() - 2, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 设置TextView的文本内容
        textView.setText(builder);
        // 垂直居中显示文本和图标
        textView.setGravity(Gravity.CENTER_VERTICAL);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/767284.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript的WebAPI

这里写目录标题 DOM 基本概念获取元素事件概念事件的三要素操作元素获取/修改表单元素属性行内样式操作类名样式操作操作节点 DOM 基本概念 DOM 全称为 Document Object Model. W3C 标准给我们提供了一系列的函数, 让我们可以操作: 网页内容 ,网页结构, 网页样式 DOM数的结构如…

【PDFBox】PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档

这篇文章&#xff0c;主要介绍PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档。 目录 一、PDFBox操作文本 1.1、读取所有页面文本内容 1.2、读取指定页面文本内容 1.3、写入文本内容 1.4、替换文本内容 &#xff08;1&#xf…

【C++】STL之list容器的模拟实现

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处。 文章目录 前言一、list的三个类的关系分析图vector和list的区别1.节点的成员变量以及构造函数2.list的迭代器 二、list的增删查改工作2.1inse…

【数据结构】24王道考研笔记——图

六、图 目录 六、图定义及基本术语图的定义有向图以及无向图简单图以及多重图度顶点-顶点间关系连通图、强连通图子图连通分量强连通分量生成树生成森林边的权、带权网/图特殊形态的图 图的存储及基本操作邻接矩阵邻接表法十字链表邻接多重表分析对比图的基本操作 图的遍历广度…

# Linux下替换文件中的颜色等控制字符的方法

Linux下替换文件中的颜色等控制字符的方法 文章目录 Linux下替换文件中的颜色等控制字符的方法1 Linux下的控制字符&#xff08;显示的文字并不是他本身&#xff09;&#xff1a;2 颜色字符范例&#xff1a;3 替换4 最后 我们在shell编程显示输出时&#xff0c;会定义文字颜色&…

ESD放电模式以及电源箝位 (power clamp )电路

目录 1.ESD的基本概念 2.ESD放电模式与泄放路径 2.1 I/O端与 Vcc或者 I/O端与 Vss 2.2 I/O端与 I/O端 2.3 Vcc&#xff08;电源端&#xff09;与Vss&#xff08;地端&#xff09; 2.4不同类型电压源 3. 电源箝位 (power clamp )电路 4.全芯片ESD保护电路系统框图 参考…

wsl2 kali linux install android studio Android SDK platforms

studio下载网址为 https://developer.android.google.cn/ 解压后在bin目录下运行studio.sh提示错误&#xff1a; unable to access android sdk add-on list 选择“setup proxy” 选择Manual proxy configuration 设置 Host name 为&#xff1a;mirrors.neusoft.edu.cn 设置…

从零开发短视频电商 单元测试(TestNG)

文章目录 简介简单示例执行测试并查看测试报告方式一 在IDEA中运行testng.xml文件方式二 在IDEA中运行测试类或者package方式三 在Maven中运行测试 统计测试覆盖率方式一 IDEA 支持详细的代码测试覆盖率统计方式二 Maven支持测试覆盖率 在IDEA中创建测试用例使用 IDEA 快速创建…

LLaMA微调记录

本文基于开源代码https://github.com/Lightning-AI/lit-llama/tree/main执行微调 其他参考链接&#xff1a; Accelerating LLaMA with Fabric: A Comprehensive Guide to Training and Fine-Tuning LLaMA - Lightning AI 结构化数据示例&#xff1a; BelleGroup/train_0.5M_…

动态sql语句

1.1 动态sql语句概述 Mybatis 的映射文件中&#xff0c;业务逻辑复杂时&#xff0c; SQL是动态变化的&#xff0c;此时在前面的学习中 SQL 就不能满足要求了。 参考的官方文档&#xff1a; 1.2 动态 SQL 之<if> 根据实体类的不同取值&#xff0c;使用不同的 SQL语句…

常见安装工具以及命令(工作常用)长期维护

dockermongodbnginxredis 1.docker 启动2.docker 安装 MongoDB3.启动nginx4.redis配置&#xff0b;安装4.1 Redis的启动和停止4.2 后台启动方式 systemctl start docker redis-server /root/myredis/redis.conf docker start mymongo docker exec -it mymongo /bin/bash 1.doc…

代码随想录算法训练营第58天 | 单调栈 ●739 每日温度 ●496下一个更大元素I ●503下一个更大元素II ●42 接雨水 ●84 柱形图中最大的矩形

#单调栈&#xff1a; 单调栈就是保持栈内元素有序。和栈与队列&#xff08;239. 滑动窗口最大值 自己写一个class来实现单调队列&#xff09;一样&#xff0c;需要我们自己维持顺序&#xff0c;没有现成的容器可以用。 通常是一维数组&#xff0c;要寻找任一个元素的右边或者…

浅谈物联网工程专业:技术融合与未来发展

技术融合与未来发展 引言1. 专业的定义与概述2. 专业的知识体系3. 专业的实践应用4. 专业的发展趋势5. 专业的就业前景结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收…

zabbix 企业级级监控(1) 监控自己

重点一 Zabbix简介在企业网络运维过程中&#xff0c;管理员必须随时关注各服务器和网络的运行状况&#xff0c;以便及时发现问题&#xff0c;尽可能减少故障的发生。当网络中的设备&#xff0c;服务器等数量较多时&#xff0c;为了更加方便&#xff0c;快捷的获得监控信息&…

【软件测试面试】腾讯数据平台笔试题-接口-自动化-数据库

数据库题 答案&#xff1a; Python编程题 答案&#xff1a; 接口参数化题 答案&#xff1a; 接口自动化题 答案&#xff1a; 以下是我收集到的比较好的学习教程资源&#xff0c;虽然不是什么很值钱的东西&#xff0c;如果你刚好需要&#xff0c;可以评论区&#…

6.3.6 利用Wireshark进行协议分析(六)----网页提取过程的协议分析

6.3.6 利用Wireshark进行协议分析&#xff08;六&#xff09;----网页提取过程的协议分析 利用Wireshark捕获网页访问过程中产生的应用协议报文&#xff0c;还原Web服务中报文的交互过程&#xff0c;为了防止网页直接从本地缓存中获取&#xff0c;我们首先需要清空浏览器保存的…

GO语言GMP模型

目录 程序入口 协程主动让出: 被动让出: schedule 监控线程 程序入口 在执行一系列检查和初始化&#xff08;创建多少个P&#xff0c;与M&#xff10;关联&#xff09;后&#xff0c;进入runtime.main,创建main goroutine,执行mian.mian。 一开始GO语言的调度只有M和G。每个M…

【代码随想录 | Leetcode | 第七天】链表 | 链表相交 | 环形链表 II

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来链表相交和环形链表 II的分享✨ 目录 前言面试题 02.07. 链表相交142. 环形链表 II总结 面试题 02.07. 链表相交 ✨题目链接点这里 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找…

C/C++ new A与new A()的区别

在C中&#xff0c;POD是“Plain Old Data”的缩写&#xff0c;即“普通旧数据”。POD data是指一种特殊类型的数据结构&#xff0c;它们具有简单的内存布局&#xff0c;没有构造函数、虚函数、私有/保护非静态数据成员&#xff0c;也没有虚继承等特性。这些数据结构可以直接通过…

k8s与集群管理

从docker讲起 终于有人把 Docker 讲清楚了&#xff0c;万字详解&#xff01; Docker资源&#xff08;CPU/内存/磁盘IO/GPU&#xff09;限制与分配指南 默认情况下&#xff0c;Docker容器是没有资源限制的&#xff0c;它会尽可能地使用宿主机能够分配给它的资源。如果不对容器资…