安卓动态添加View
在安卓应用中,有很多时候需要动态添加View。比如从后台获取商品列表,根据商品数量在页面渲染对应数量的条目,这时候就需要动态添加View。
1.动态添加View的方法
动态添加View有两种方法:
- 由代码生成子View:这种方式很繁琐,布局效果也不直观,而且很多属性设置不了(也可能是我没找对方法);
- 从xml读取布局,然后动态设置信息:推荐该方式,配置xml时,可以直接看到效果,可设置的参数也更多。
接下来就用代码演示下如何使用这两种方式动态添加View。
注:子View也可以写在父View中,设置visible为GONE即可,在createItem最后添加一行item.setVisibility(View.VISIBLE);
。
2. 代码实现
父View布局activity_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ScrollViewandroid:layout_width="match_parent"android:layout_height="480dp"android:layout_gravity="center_horizontal|top"android:layout_margin="10dp"><LinearLayoutandroid:id="@+id/list_items"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" /></ScrollView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"><Buttonandroid:id="@+id/list_switch_model"android:layout_width="100dp"android:layout_height="70dp"android:layout_gravity="center"android:layout_marginRight="20dp"android:text="Switch Model" /><Buttonandroid:id="@+id/list_add_item"android:layout_width="100dp"android:layout_height="70dp"android:layout_gravity="center"android:layout_marginLeft="20dp"android:text="Add Item" /></LinearLayout>
</LinearLayout>
子View布局activity_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/item"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:orientation="horizontal"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:gravity="right|center"android:orientation="horizontal"><ImageViewandroid:id="@+id/item_img"android:layout_width="48dp"android:layout_height="48dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:padding="10dp"android:src="@drawable/common_item" /></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="center"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:gravity="left|center"android:orientation="vertical"><TextViewandroid:id="@+id/item_index"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="index: item name"android:textColor="@color/black"android:textSize="6pt" /><TextViewandroid:id="@+id/item_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="name: item name"android:textColor="@color/black"android:textSize="6pt" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center_vertical"android:layout_marginRight="10dp"android:gravity="right|center"android:orientation="horizontal"><ImageViewandroid:id="@+id/item_edit"android:layout_width="48dp"android:layout_height="48dp"android:layout_marginRight="10dp"android:padding="10dp"android:src="@drawable/common_edit" /><ImageViewandroid:id="@+id/item_delete"android:layout_width="48dp"android:layout_height="48dp"android:layout_marginRight="10dp"android:padding="10dp"android:src="@drawable/common_delete" /></LinearLayout></LinearLayout>
</LinearLayout>
activity类:
package org.tao.hetools.activities;import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;import androidx.activity.ComponentActivity;
import androidx.annotation.Nullable;import org.tao.hetools.R;
import org.tao.hetools.entities.ItemInfo;import java.util.ArrayList;
import java.util.List;public class DynamicViewActivity extends ComponentActivity {private int index = 0;private boolean createViewFromXml = true;private List<ItemInfo> itemInfos = new ArrayList<>();private LinearLayout listItemsLayout;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);listItemsLayout = findViewById(R.id.list_items);initButton();initDynamicView();}private void initDynamicView() {if (listItemsLayout == null) {return;}listItemsLayout.removeAllViews();for (ItemInfo itemInfo : itemInfos) {listItemsLayout.addView(createViewFromXml ? createViewFromCode(itemInfo) : createViewFromCode(itemInfo));}}private void initButton() {findViewById(R.id.list_add_item).setOnClickListener(view -> {if (listItemsLayout == null) {return;}ItemInfo itemInfo = new ItemInfo(index, "name " + index, R.drawable.common_item);index++;itemInfos.add(itemInfo);listItemsLayout.addView(createViewFromXml ? createItem(itemInfo) : createViewFromCode(itemInfo));});findViewById(R.id.list_switch_model).setOnClickListener(view -> {itemInfos.clear();listItemsLayout.removeAllViews();createViewFromXml = !createViewFromXml;});}/*** 在代码中生成布局作为子view的布局** @param itemInfo item信息* @return item view*/private View createViewFromCode(ItemInfo itemInfo) {// item开头的图标layoutImageView itemImage = new ImageView(this);itemImage.setImageResource(R.drawable.common_item);itemImage.setMaxHeight(136);// 这个高度跟dp的换算,需要根据屏幕分辨率重新计算。下同itemImage.setMaxWidth(136);itemImage.setLeft(10);itemImage.setRight(10);itemImage.setPadding(5, 5, 5, 5);itemImage.setAdjustViewBounds(true);LinearLayout imageLayout = new LinearLayout(this);imageLayout.setOrientation(LinearLayout.HORIZONTAL);imageLayout.addView(itemImage);// item信息layoutTextView index = new TextView(this);index.setText("index: " + itemInfo.getIndex());index.setTextSize(10);TextView name = new TextView(this);name.setText("name: " + itemInfo.getName());name.setTextSize(10);LinearLayout infoLayout = new LinearLayout(this);infoLayout.setOrientation(LinearLayout.VERTICAL);infoLayout.addView(index);infoLayout.addView(name);// 操作layoutImageView edit = new ImageView(this);edit.setImageResource(R.drawable.common_edit);edit.setMaxHeight(136);edit.setMaxWidth(136);edit.setAdjustViewBounds(true);ImageView delete = new ImageView(this);delete.setImageResource(R.drawable.common_delete);delete.setMaxHeight(136);delete.setMaxWidth(136);delete.setAdjustViewBounds(true);LinearLayout operateLayout = new LinearLayout(this);operateLayout.setOrientation(LinearLayout.HORIZONTAL);operateLayout.addView(edit);operateLayout.addView(delete);// 子view的信息LinearLayout layout = new LinearLayout(this);layout.setOrientation(LinearLayout.HORIZONTAL);layout.addView(imageLayout);layout.addView(infoLayout);layout.addView(operateLayout);edit.setOnClickListener(view -> {// todo 此处处理edit的点击事件Log.i("itemInfoList: ", itemInfos.toString());});delete.setOnClickListener(view -> {itemInfos.remove(itemInfo);listItemsLayout.removeView(layout);});return layout;}/*** 从xml文件获取布局作为子view的布局** @param itemInfo item信息* @return item view*/private View createItem(ItemInfo itemInfo) {LinearLayout inflate = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_item, null);LinearLayout item = inflate.findViewById(R.id.item);((ImageView) item.findViewById(R.id.item_img)).setImageResource(itemInfo.getImageResourceId());((TextView) item.findViewById(R.id.item_index)).setText("index: " + itemInfo.getIndex());((TextView) item.findViewById(R.id.item_name)).setText("name: " + itemInfo.getName());item.findViewById(R.id.item_edit).setOnClickListener(view -> {// todo 此处处理edit的点击事件Log.i("itemInfoList: ", itemInfos.toString());});item.findViewById(R.id.item_delete).setOnClickListener(view -> {itemInfos.remove(itemInfo);listItemsLayout.removeView(item);});((ViewGroup) item.getParent()).removeAllViews();return item;}
}
相关文章:
安卓动态添加View
在安卓应用中,有很多时候需要动态添加View。比如从后台获取商品列表,根据商品数量在页面渲染对应数量的条目,这时候就需要动态添加View。 1.动态添加View的方法 动态添加View有两种方法: 由代码生成子View:这种方式…...
前端预览pdf文件流
需求 后端接口返回pdf文件流,实现新窗口预览pdf。 解决方案 把后端返回的pdf文件流转为blob路径,利用浏览器直接预览。 具体实现步骤 1、引入axios import axios from axios;2、创建预览方法(具体使用时将axios的请求路径替换为你的后端…...

【测试工具JMeter篇】JMeter性能测试入门级教程(一)出炉,测试君请各位收藏了!!!
一、前言 Apache JMeter是纯Java的开源软件,最初由Apache软件基金会的Stefano Mazzocchi开发,旨在加载测试功能行为和测量性能。可以使用JMeter进行性能测试,即针对重负载、多用户和并发流量测试Web应用程序。 我们选择JMeter原因 是否测试过…...

【zookeeper03】消息队列与微服务之zookeeper集群部署
ZooKeeper 集群部署 1.ZooKeeper 集群介绍 ZooKeeper集群用于解决单点和单机性能及数据高可用等问题。 集群结构 Zookeeper集群基于Master/Slave的模型 处于主要地位负责处理写操作)的主机称为Leader节点,处于次要地位主要负责处理读操作的主机称为 follower 节点…...

从 Llama 1 到 3.1:Llama 模型架构演进详解
编者按: 面对 Llama 模型家族的持续更新,您是否想要了解它们之间的关键区别和实际性能表现?本文将探讨 Llama 系列模型的架构演变,梳理了 Llama 模型从 1.0 到 3.1 的完整演进历程,深入剖析了每个版本的技术创新&#…...

UE5肉鸽游戏教程学习
学习地址推荐:UE5肉鸽项目实战教程_哔哩哔哩_bilibili...

Vue3 - 详细实现虚拟列表前端虚拟滚动列表解决方案,vue3长列表优化之虚拟列表,解决列表动态高度不固定高度及图片视频图文异步请求加载问题,虚拟列表DOM大量数据同时加载渲染卡顿太慢及下滑列表闪烁
前言 Vue2 版本,请访问 这篇文章 在 vue3 项目开发中,详解实现虚拟列表高度不固定(不定高)且复杂含有图片视频等复杂虚拟列表教程,决列表每项高度不确定及img图像或视频的加载方案,利用缓冲区技术解决用户浏览时渲染不及时列表闪烁白屏/列表加载闪屏,解vue3实现虚拟列表优…...

英语知识网站开发:Spring Boot框架技巧
摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了英语知识应用网站的开发全过程。通过分析英语知识应用网站管理的不足,创建了一个计算机管理英语知识应用网站的方案。文章介绍了英语知识应用网站的系…...
基于lvgl+ST7735制作一款esp8285的控制面板程序
要在ESP8285上使用LVGL和ST7735创建一个控制面板程序,你需要遵循以下步骤。这个过程包括设置开发环境,连接硬件,编写代码,以及调校和优化。 所需硬件 ESP8285 开发板:像NodeMCU之类的开发板。ST7735 显示屏:通常是1.8英寸或2.0英寸的SPI接口显示屏。电源和连接线:用于连…...
MySQL 索引详解
在数据库的世界中,索引就像是一本巨大书籍的目录,它能够极大地提高数据检索的效率。在 MySQL 中,索引的合理使用对于数据库的性能至关重要。本文将深入探讨 MySQL 索引的各个方面。 一、索引的概念与作用 1. 什么是索引? 索引是一…...

区块链学习笔记(1)--区块、链和共识 区块链技术入门
常见的hash算法: 文件防篡改:MD5比特币挖矿:SHA256证明数据片段:Merkle root文本去重:SimHash 区块 区块(block)由区块头(block header)和交易列表(transac…...

【Android+多线程】IntentService 知识总结:应用场景 / 使用步骤 / 源码分析
定义 IntentService 是 Android中的一个封装类,继承自四大组件之一的Service 功能 处理异步请求 & 实现多线程 应用场景 线程任务 需 按顺序、在后台执行 最常见的场景:离线下载不符合多个数据同时请求的场景:所有的任务都在同一个T…...

Python Tornado框架教程:高性能Web框架的全面解析
Python Tornado框架教程:高性能Web框架的全面解析 引言 在现代Web开发中,选择合适的框架至关重要。Python的Tornado框架因其高性能和非阻塞I/O特性而备受青睐。它特别适合处理大量并发连接的应用,比如聊天应用、实时数据处理和WebSocket服务…...
通过端口测试验证网络安全策略
基于网络安全需求,项目中的主机间可能会有不同的网络安全策略,这当然是好的,但很多时候,在解决网络安全问题的时候,同时引入了新的问题,如k8s集群必须在主机间开放udp端口,否则集群不能正常的运…...

Excel把其中一张工作表导出成一个新的文件
excel导出一张工作表 一个Excel表里有多个工作表,怎么才能导出一个工作表,让其生成新的Excel文件呢? 第一步:首先打开Excel表格,然后选择要导出的工作表的名字,比如“Sheet1”,把鼠标放到“She…...
第四份工作的环境配置
最近在内网中工作,会遇到不少的环境问题. 下面记录一下这个过程中的挑战: 环境:内网,连接不到外网. 如何配置开发环境: 方法0: 在服务器上安装环境. 但是服务器上没有相应的python包.因为python包是从外界获得的.并且,这些python包不能同步更新.所以,在服务器上直接搭建环…...
SpringBoot开发——Maven多模块工程最佳实践及详细示例
文章目录 一、前言二、Maven多模块工程的最佳实践1、项目结构清晰2、依赖管理统一3、插件配置统一4、版本控制一致5、模块间通信简化 三、详细示例1、项目结构2、父模块(parent)的pom.xml文件3、子模块(module-api)的pom.xml文件4…...

C 语言面向对象
面向对象的基本特性:封装,继承,多态 1.0 面向过程概念 当我们在编写程序时,通常采用以下步骤: 1. 将问题的解法分解成若干步骤 2. 使用函数分别实现这些步骤 3. 依次调用这些函数 这种编程风格的被称作 面向过程…...

无人机探测:光电侦测核心技术算法详解!
核心技术 双光谱探测跟踪: 可见光成像技术:利用无人机表面反射的自然光或主动光源照射下的反射光,通过高灵敏度相机捕捉图像。该技术适用于日间晴朗天气下的无人机探测,具有直观、易于识别目标的特点。 红外成像技术࿱…...

ffmpeg视频滤镜:替换部分帧-freezeframes
滤镜描述 freezeframes 官网地址 > FFmpeg Filters Documentation 这个滤镜接收两个输入,然后会将第一个视频中的部分帧替换为第二个视频的某一帧。 滤镜使用 参数 freezeframes AVOptions:first <int64> ..FV....... set first fra…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...