Android 实现动态换行显示的 TextView 列表

在开发 Android 应用程序时,我们经常需要在标题栏中显示多个 TextView,而这些 TextView 的内容长度可能不一致。如果一行内容过长,我们希望它们能自动换行;如果一行占不满屏幕宽度,则保持在一行内。本文将带我们一步步实现这个需求,使用 ConstraintLayout 和 Flow 组件来轻松布局我们的 TextView 列表。
🖼 布局设计
首先,我们需要设计一个布局文件,其中包含 ConstraintLayout 和多个 TextView。我们将使用 Flow 组件来管理这些 TextView 的布局,确保它们在一行占满后自动换行,而不是强制显示在一行内。
📄 XML 布局文件
在 res/layout 目录下创建或编辑一个布局文件(如 activity_main.xml),并按照以下内容进行布局:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"><!-- 定义多个 TextView -->
<TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="TextView 1"android:textSize="16sp" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="TextView 2"android:textSize="16sp" /><!-- 更多 TextView --><!-- Flow 布局,用于管理 TextView 的排列 -->
<androidx.constraintlayout.helper.widget.Flowandroid:id="@+id/flow"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintTop_toTopOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintEnd_toEndOf="parent"app:flow_wrapMode="chain"app:flow_horizontalStyle="packed"app:flow_verticalStyle="spread_inside"app:flow_maxElementsWrap="4"app:flow_horizontalGap="8dp"app:flow_verticalGap="8dp"app:flow_firstHorizontalStyle="packed"app:flow_firstVerticalStyle="spread_inside"app:flow_horizontalAlign="start"app:flow_verticalAlign="top"app:flow_referencedIds="textView1,textView2" /></androidx.constraintlayout.widget.ConstraintLayout>
在这个布局文件中,我们使用了 ConstraintLayout 作为根布局,然后定义了多个 TextView。Flow 组件用于管理这些 TextView 的排列方式。通过 flow_wrapMode、flow_horizontalStyle 等属性,我们可以控制 TextView 如何排列,以及在占满一行后如何换行。
🔧 动态添加 TextView
有时,我们需要根据某些条件动态地添加 TextView。例如,我们可能会从服务器获取一些数据,并根据这些数据生成相应数量的 TextView。下面是如何在代码中动态添加 TextView 并将它们添加到 Flow 中的方法。
📝 Kotlin 代码实现
在我们的 Activity 或 Fragment 中,我们可以通过以下代码动态添加 TextView:
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.helper.widget.Flow
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.childrenclass MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val constraintLayout = findViewById<ConstraintLayout>(R.id.constraintLayout)val flow = findViewById<Flow>(R.id.flow)// 模拟从服务器获取的数据val textViews = listOf("Text 1", "Text 2", "Text 3", "Text 4")// 动态创建 TextView 并添加到 ConstraintLayout 和 Flow 中textViews.forEachIndexed { index, text ->val textView = TextView(this).apply {id = View.generateViewId()this.text = texttextSize = 16f}constraintLayout.addView(textView)flow.addView(textView)}// 更新 Flow 引用的子视图 id 列表flow.referencedIds = constraintLayout.children.map { it.id }.toIntArray()
}
}
🔍 代码解析
- 动态生成
TextView: 使用TextView(this).apply { ... }语法来创建TextView,并设置其文本内容和样式。 - 添加到布局中: 通过
constraintLayout.addView(textView)将新创建的TextView添加到ConstraintLayout中。 - 添加到
Flow中: 使用flow.addView(textView)将TextView添加到Flow中,以便其能够根据需要自动排列和换行。 - 更新引用 ID: 最后,更新
Flow的referencedIds属性,以确保Flow正确引用到所有的TextView。
🔍 进一步优化
在实现基本功能之后,我们可以进一步优化布局和代码,例如:
- 优化样式: 可以使用自定义样式来统一管理
TextView的外观,以减少代码中的重复部分。 - 调整
Flow的属性: 我们可以根据具体需求调整Flow的属性,比如flow_horizontalGap、flow_verticalGap等,以实现更好的视觉效果。 - 处理更多的动态内容: 如果
TextView的内容和数量是从网络或数据库中获取的,建议在添加TextView前做一定的数据验证和处理。
🎉 结论
通过使用 ConstraintLayout 和 Flow 组件,我们可以轻松实现动态布局的 TextView 列表,并且能够根据内容自动换行。这个方法不仅简洁高效,而且扩展性强,适用于各种动态布局的需求。希望我们在项目中能用上这个技巧,并根据具体需求进一步优化它!💪
相关文章:
Android 实现动态换行显示的 TextView 列表
在开发 Android 应用程序时,我们经常需要在标题栏中显示多个 TextView,而这些 TextView 的内容长度可能不一致。如果一行内容过长,我们希望它们能自动换行;如果一行占不满屏幕宽度,则保持在一行内。本文将带我们一步步…...
Golang | Leetcode Golang题解之第352题将数据流变为多个不相交区间
题目: 题解: type SummaryRanges struct {*redblacktree.Tree }func Constructor() SummaryRanges {return SummaryRanges{redblacktree.NewWithIntComparator()} }func (ranges *SummaryRanges) AddNum(val int) {// 找到 l0 最大的且满足 l0 < val…...
Ubuntu安装mysql 以及远程连接mysql Windows—适合初学者的讲解(详细)
目录 准备工作 一.Xshell中操作 (1)在虚拟机中安装mysql (2)连接Windows数据库 (3)进入linux数据库。 (4)修改mysql配置文件 二.Windows命令窗口操作 需要软件虚拟机,Xsh…...
【数学建模】MATLAB快速入门
文章目录 1. MATLAB界面与基本操作1.1 MATLAB的基本操作 2. MATLAB字符串和文本2.1 string变量2.2 char变量 3. MATLAB的矩阵运算 1. MATLAB界面与基本操作 初始界面: 刚开始的界面只要一个命令行窗口,为了使编辑界面出现我们需要新建一个文件ÿ…...
【ubuntu24.04】k8s 部署5:配置calico 镜像拉取
kubeadm - 中国大陆版建议:初始化Kubeadm –apiserver-advertise-address 这个地址是本地用于和其他节点通信的IP地址 –pod-network-cidr pod network 地址空间 sudo kubeadm init --image-repository registry.aliyuncs.com/google_containers --apiserver-advertise-add…...
Elasticsearch 的数据备份与恢复
在生产环境中,数据的安全性和可靠性至关重要。对于基于 Elasticsearch 的系统而言,数据备份与恢复是确保数据完整性、应对灾难恢复的关键操作。本文将详细介绍 Elasticsearch 中如何进行数据备份与恢复,帮助管理员构建一个可靠的数据保护策略…...
Ps:首选项 - 暂存盘
Ps菜单:编辑/首选项 Edit/Preferences 快捷键:Ctrl K Photoshop 首选项中的“暂存盘” Scratch Disks选项卡通过合理配置和管理暂存盘,可以显著提高 Photoshop 的运行性能,特别是在处理复杂的设计项目或大型图像文件时。选择合适…...
力扣217题详解:存在重复元素的多种解法与复杂度分析
在本篇文章中,我们将详细解读力扣第217题“存在重复元素”。通过学习本篇文章,读者将掌握如何使用多种方法来解决这一问题,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。 问题描述 力扣第217…...
享元模式:轻量级对象共享,高效利用内存
享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少对象数量、降低内存消耗和提高系统性能。它通过共享相似对象的内部状态,减少重复创建的对象。下面将具体介绍享元模式的各个方面: 组成 抽象享元࿰…...
人工智能-自然语言处理(NLP)
人工智能-自然语言处理(NLP) 1. NLP的基础理论1.1 语言模型(Language Models)1.1.1 N-gram模型1.1.2 词嵌入(Word Embeddings)1.1.2.1 词袋模型(Bag of Words, BoW)1.1.2.2 TF-IDF&a…...
基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(三)---创建自定义激光雷达Componet组件
前言 本系列教程旨在使用UE5配置一个具备激光雷达深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博…...
C++ 设计模式——策略模式
策略模式 策略模式主要组成部分例一:逐步重构并引入策略模式第一步:初始实现第二步:提取共性并实现策略接口第三步:实现具体策略类第四步:实现上下文类策略模式 UML 图策略模式的 UML 图解析 例二:逐步重构…...
【书生大模型实战营(暑假场)闯关材料】基础岛:第3关 浦语提示词工程实践
1.配置环境时遇到的问题 注意要使用terminal,而不是jupyter。 否则退出TMUX会话时,会出问题。 退出TMUX会话命令如下: ctrlB D # 先按CTRLB 随后按D另外一个是,端口转发命令 ssh -p XXXX rootssh.intern-ai.org.cn -CNg -L …...
C++ | Leetcode C++题解之第350题两个数组的交集II
题目: 题解: class Solution { public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {sort(nums1.begin(), nums1.end());sort(nums2.begin(), nums2.end());int length1 nums1.size(), length2 nums2…...
遗传算法原理与实战(python、matlab)
遗传算法 1.什么是遗传算法 遗传算法(Genetic Algorithm,简称GA)是一种基于生物进化论和遗传学原理的全局优化搜索算法。它通过模拟自然界中生物种群的遗传机制和进化过程来解决复杂问题,如函数优化、组合优化、机器学习等。遗传…...
《黑神话:悟空》媒体评分解禁 M站均分82
《黑神话:悟空》媒体评分现已解禁,截止发稿时,M站共有43家媒体评测,均分为82分。 部分媒体评测: God is a Geek 100: 毫无疑问,《黑神话:悟空》是今年最好的动作游戏之一ÿ…...
安卓中携程和线程的区别。携程是指什么?
在安卓和其他编程环境中,协程(Coroutine)和线程(Thread)是两种不同的并发处理机制。它们各自有独特的特点和适用场景: 线程(Thread): 线程是操作系统能够进行运算调度的最…...
部署flannel网络(master服务器执行)遇到错误
出现错误 “The connection to the server 192.168.0.23:6443 was refused - did you specify the right host or port?” 的原因通常是因为 Kubernetes API 服务器未能启动或无法访问。以下是一些可能的原因和解决方案: 解决方案 确认 Kubernetes API 服务器的状…...
超越IP-Adapter!阿里提出UniPortrait,可通过文本定制生成高保真的单人或多人图像。
阿里提出UniPortrait,能根据用户提供的文本描述,快速生成既忠实于原图又能灵活调整的个性化人像,用户甚至可以通过简单的句子来描述多个不同的人物,而不需要一一指定每个人的位置。这种设计大大简化了用户的操作,提升了…...
使用托管竞价实例在Amazon SageMaker上运行机器学习训练
这是本系列文章的第二篇,旨在通过动手实践,帮助大家学习亚马逊云科技的生成式AI相关技能。通过这些文章,大家将掌握如何利用亚马逊云科技的各类服务来应用AI技术。 那么让我们开始今天的内容吧! 介绍 什么是Amazon SageMaker …...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
