Android可换行的RadioGroup
Android可换行的RadioGroup,有时候需要换行显示的单选列表,当然可以有多种实现方式,比如recycleview或者listview实现,本文采用的是RadioGroup+rediobutton方式实现。

一、首先自定义view
public class WrapRadioGroup extends RadioGroup {private static final String TAG = "RadioGroupEx";public WrapRadioGroup(Context context) {super(context);}public WrapRadioGroup(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);//调用ViewGroup的方法,测量子viewmeasureChildren(widthMeasureSpec, heightMeasureSpec);//最大的宽int maxWidth = 0;//累计的高int totalHeight = 0;//当前这一行的累计行宽int lineWidth = 0;//当前这行的最大行高int maxLineHeight = 0;//用于记录换行前的行宽和行高int oldHeight;int oldWidth;int count = getChildCount();//假设 widthMode和heightMode都是AT_MOSTfor (int i = 0; i < count; i++) {View child = getChildAt(i);MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();//得到这一行的最高oldHeight = maxLineHeight;//当前最大宽度oldWidth = maxWidth;int deltaX = child.getMeasuredWidth() + params.leftMargin + params.rightMargin;if (lineWidth + deltaX + getPaddingLeft() + getPaddingRight() > widthSize) {//如果折行,height增加//和目前最大的宽度比较,得到最宽。不能加上当前的child的宽,所以用的是oldWidthmaxWidth = Math.max(lineWidth, oldWidth);//重置宽度lineWidth = deltaX;//累加高度totalHeight += oldHeight;//重置行高,当前这个View,属于下一行,因此当前最大行高为这个child的高度加上marginmaxLineHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin;
// Log.v(TAG, "maxHeight:" + totalHeight + "---" + "maxWidth:" + maxWidth);} else {//不换行,累加宽度lineWidth += deltaX;//不换行,计算行最高int deltaY = child.getMeasuredHeight() + params.topMargin + params.bottomMargin;maxLineHeight = Math.max(maxLineHeight, deltaY);}if (i == count - 1) {//前面没有加上下一行的搞,如果是最后一行,还要再叠加上最后一行的最高的值totalHeight += maxLineHeight;//计算最后一行和前面的最宽的一行比较maxWidth = Math.max(lineWidth, oldWidth);}}//加上当前容器的padding值maxWidth += getPaddingLeft() + getPaddingRight();totalHeight += getPaddingTop() + getPaddingBottom();setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : maxWidth,heightMode == MeasureSpec.EXACTLY ? heightSize : totalHeight);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int count = getChildCount();//pre为前面所有的child的相加后的位置int preLeft = getPaddingLeft();int preTop = getPaddingTop();//记录每一行的最高值int maxHeight = 0;for (int i = 0; i < count; i++) {View child = getChildAt(i);MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();//r-l为当前容器的宽度。如果子view的累积宽度大于容器宽度,就换行。if (preLeft + params.leftMargin + child.getMeasuredWidth() + params.rightMargin + getPaddingRight() > (r - l)) {//重置preLeft = getPaddingLeft();//要选择child的height最大的作为设置preTop = preTop + maxHeight;maxHeight = getChildAt(i).getMeasuredHeight() + params.topMargin + params.bottomMargin;} else { //不换行,计算最大高度maxHeight = Math.max(maxHeight, child.getMeasuredHeight() + params.topMargin + params.bottomMargin);}//left坐标int left = preLeft + params.leftMargin;//top坐标int top = preTop + params.topMargin;int right = left + child.getMeasuredWidth();int bottom = top + child.getMeasuredHeight();//为子view布局child.layout(left, top, right, bottom);//计算布局结束后,preLeft的值preLeft += params.leftMargin + child.getMeasuredWidth() + params.rightMargin;}}}
二、布局直接引用
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><csu.xiaoya.robotApp.ui.view.WrapRadioGroupandroid:id="@+id/rg_bls"android:layout_width="438dp"android:layout_height="179dp"android:layout_below="@id/monitor_remd"android:layout_alignParentRight="true"android:layout_marginTop="@dimen/dp_15"android:layout_marginRight="@dimen/dp_24"android:orientation="horizontal"android:padding="1dp"app:maxWidth="300dp"><RadioButtonandroid:id="@+id/rb_date_day"android:layout_width="@dimen/dp_84"android:layout_height="@dimen/dimen_48"android:background="@drawable/bls_am_2h_sg"android:button="@null"android:checked="true"android:layout_marginLeft="@dimen/dp_10"android:gravity="center"android:text="随机血糖"android:textColor="@color/white"android:textSize="@dimen/sp_10" /><RadioButtonandroid:id="@+id/rb_date_week"android:layout_width="@dimen/dp_84"android:layout_height="@dimen/dimen_48"android:layout_marginLeft="@dimen/dp_10"android:background="@drawable/bls_am_2h_sg"android:button="@null"android:gravity="center"android:text="空腹血糖"android:textColor="@color/white"android:textSize="@dimen/sp_10" /><RadioButtonandroid:layout_width="@dimen/dp_84"android:layout_height="@dimen/dimen_48"android:layout_marginLeft="@dimen/dp_10"android:background="@drawable/bls_am_2h_sg"android:button="@null"android:gravity="center"android:text="早餐后2小时"android:textColor="@color/white"android:textSize="@dimen/sp_10" /><RadioButtonandroid:layout_width="@dimen/dp_84"android:layout_height="@dimen/dimen_48"android:layout_marginLeft="@dimen/dp_10"android:background="@drawable/bls_am_2h_sg"android:button="@null"android:gravity="center"android:text="早餐后2小时"android:textColor="@color/white"android:textSize="@dimen/sp_10" /><RadioButtonandroid:layout_width="@dimen/dp_84"android:layout_height="@dimen/dimen_48"android:layout_marginLeft="@dimen/dp_10"android:layout_marginTop="@dimen/dp_10"android:background="@drawable/bls_am_2h_sg"android:button="@null"android:gravity="center"android:text="早餐后2小时"android:textColor="@color/white"android:textSize="@dimen/sp_10" /></csu.xiaoya.robotApp.ui.view.WrapRadioGroup></LinearLayout>
三、背景样式bls_am_2h_sg
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:width="84dp" android:height="48dp" android:state_checked="false"><shape android:shape="rectangle"><solid android:color="#ff27b074" /><corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" /></shape></item><item android:width="88dp" android:height="50dp" android:state_checked="true"><shape android:shape="rectangle"><solid android:color="#ff27b074" /><corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" /></shape></item>
</selector>
四、大功告成
相关文章:
Android可换行的RadioGroup
Android可换行的RadioGroup,有时候需要换行显示的单选列表,当然可以有多种实现方式,比如recycleview或者listview实现,本文采用的是RadioGrouprediobutton方式实现。 一、首先自定义view public class WrapRadioGroup extends RadioGroup {pr…...
【ASP.NET Core 基础知识】--环境设置
一、简介 1.1 .NET Core SDK 概述 .NET Core SDK(Software Development Kit)是Microsoft推出的一个开源跨平台框架,用于开发和部署.NET应用程序。它是.NET Core平台的核心组件之一,为开发者提供了在多个操作系统上构建高性能、可…...
docker/华为云cce 部署nacos 2.3.0 集群模式
镜像地址 https://hub.docker.com/r/nacos/nacos-server 版本 nacos/nacos-server:v2.3.0-slim 关键环境变量 使用mysql数据源 变量值备注MODEcluster启用集群模式MYSQL_SERVICE_DB_NAME数据库名MYSQL_SERVICE_USER数据库用户名MYSQL_SERVICE_PASSWORD数据库密码SPRING_D…...
Doris 数据模型—Aggregate 模型
Doris 数据模型—Aggregate 模型 文章目录 Doris 数据模型—Aggregate 模型基本概念Aggregate 模型示例1:导入数据聚合示例2:保留明细数据示例3:导入数据与已有数据聚合Aggregate 模型限制Aggregate 模型使用场景本文主要从逻辑层面,描述 Doris 的数据模型,以帮助用户更好…...
数据库管理-第130期 JSON二元性(20240109)
数据库管理130期 2024-01-09 第130期 JSON二元性(20240109)1 简介2 关系型表和JSON存储的优劣3 Oracle JSON关系型二元性视图总结 第130期 JSON二元性(20240109) 上周,又双叒飞了一趟上海,也是2024年第一飞…...
k8s--动态pvc和pv
前情回顾 存储卷: emptyDir 容器内部,随着pod销毁,emptyDir也会消失 不能做数据持久化 hostPath:持久化存储数据 可以和节点上目录做挂载。pod被销毁了数据还在 NFS:一台机器,提供pod内容器所有的挂载点…...
C++:常量
const的最初动机 const的使用方法 使用const的好处是允许指定一种语义上的约束,即某种对象不能被修改,且由编译器具体实施这种约束。 const声明格式:const 类型名 对象名;修饰普通变量,时期不能被随意修改 【注意】1.C中的const…...
java JDBC 连接数据库
必须先插入工具包 DataSource ds JdbcHelper.getDs();System.out.println(ds);JdbcTemplate jdbcTemplatenew JdbcTemplate(ds);System.out.println(jdbcTemplate);//新增String sql1"insert into biao values(null,?,?,?)";int ijdbcTemplate.update(sql1,"…...
图神经网络|5.消息传递的计算方法 6.多层GNN的作用
5.消息传递的计算方法 边的存放方式 注意,在实际的边的实现方式中,并不是以邻接矩阵来进行实现的,这是因为在图的更新中,用邻接矩阵进行更新所占用的时间开销相对大,二是因为领接矩阵占用的空间大(N方&am…...
构建中国人自己的私人GPT
创作不易,请大家多鼓励支持。 在现实生活中,很多人的资料是不愿意公布在互联网上的,但是我们又要使用人工智能的能力帮我们处理文件、做决策、执行命令那怎么办呢?于是我们构建自己或公司的私人GPT变得非常重要。 先看效果 一、…...
添加气泡与菜单
目录 1、添加气泡 1.1、文本提示气泡 1.2、带按钮的提示气泡 1.3、自定义气泡 2、菜单 2.1、创建默认样式的菜单 2.2、创建自定义样式的菜单 1、添加气泡 Popup属性可绑定在组件上显示气泡弹窗提示,设置弹窗内容、交互逻辑和显示状态。主要用于…...
python代码练习:双指针法
题目一:移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不…...
C++系列十七:访问控制符
访问权限控制符 一、public访问权限二、private访问权限三、protected访问权限 在C中,访问权限控制符用于限制类成员的访问权限,主要包括public、private和protected三种。这些访问权限控制符用于控制类成员的访问级别,从而保证数据的封装性和…...
postgresql 最简主从配置
实验目的 配置一个最简的主从环境,了解基本的主从配置。 环境参数 操作系统CentOS Linux release 7.9.2009 (Core)数据库版本PostgreSQL 10.23主库端口15431备库端口15432 因为只是做实验,所以主备库放在同一台机器上,仅通过端口区分主备…...
ubuntu 安装 anaconda
ubuntu 安装 anaconda 下载 wget https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh安装 bash Anaconda3-2023.09-0-Linux-x86_64.sh2.1 回车继续 2.2 许可协议 输入 q 退出阅读许可协议 2.3 输入 yes 接受 许可协议 2.4 设置 anaconda 安装位置 如不需…...
DOM 被劫持
文档对象模型(DOM)充当着 HTML 和 JavaScript 之间的接口,搭建起静态内容与动态交互之间的桥梁,对现代 Web 开发而言,DOM 的作用不可或缺。 然而,DOM 也有一个致命的陷阱 —— DOM 劫持。DOM 劫持是指当 H…...
PIG框架学习2——资源服务器的配置详解
一、前言 1、pig资源服务器的配置 Spring Security oauth2相关的依赖是在pigx-common-security模块中引入的,其他模块需要进行token鉴权的,需要在微服务中引入pigx-common-security模块的依赖,从而间接引入相关的Spring security oauth2依赖…...
vue+element ui实现图片上传并拖拽进行图片排序
用到的技术栈: vue2element Uivue-dragging 如何使用: 第一步: 安装 npm install awe-dnd --save第二步: 引入 main.js 文件 // 引入组件 import VueDND from awe-dnd // 添加至全局 Vue.use(VueDND)具体项目代码 <el-form-item label"封面…...
国产服务器 BIOS下组建RADI不同RAID卡-超详细
国产服务器 长城 组建Raid的方法 说明 大多数国产服务器通用型服务器进入BIOS的都是按DEL键。 9361RAID卡组建方法 在服务器启动过程中,按下DEL键进入BIOS界面。 进入设备管理器,选择AVAGO MegaRAID页签。 3. 进入RAID卡设备,选择Main Me…...
UE4 4.21-4.27使用编辑器蓝图EditorBlueprint方法
在UE4 4.21中,编辑器蓝图(Editor Blueprint)是一个强大的工具,允许开发者扩展和自定义Unreal编辑器的功能。通过编辑器蓝图,我们可以创建自定义的工具和功能,以优化开发流程。 本教程将指导您如何在UE4 4.…...
Python自动化办公:3分钟搞定Outlook邮件批量导出(附完整代码)
Python自动化办公:3分钟搞定Outlook邮件批量导出(附完整代码) 每天早晨打开Outlook,面对堆积如山的未读邮件,你是否也感到一阵窒息?市场部的周报、客户的需求变更、财务部的报销提醒……重要信息散落在上百…...
小米设备集成终极测试指南:确保HomeAssistant稳定运行的7个关键步骤
小米设备集成终极测试指南:确保HomeAssistant稳定运行的7个关键步骤 【免费下载链接】hass-xiaomi-miot Automatic integrate all Xiaomi devices to HomeAssistant via miot-spec, support Wi-Fi, BLE, ZigBee devices. 小米米家智能家居设备接入Hass集成 项目地…...
001、性能优化基础:慢SQL诊断与执行计划分析
昨天凌晨又被告警短信吵醒了,线上某核心接口的P99响应时间飙到了3秒。登录服务器一看,MySQL的CPU已经跑满,processlist里堆了二十几个相同的查询——又是慢SQL惹的祸。这种场景咱们做后端开发的太熟悉了,今天就来聊聊怎么系统性地…...
mysql进阶--锁
锁的概述: 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问…...
除了Omnipeek,你的8812BU网卡还能怎么玩?Win10下的另类WiFi抓包与网络诊断实战
解锁Realtek 8812BU网卡的隐藏潜能:Windows 10下的WiFi抓包与网络诊断全攻略 当你手握一块Realtek 8812BU无线网卡时,可能只把它当作普通的网络连接工具。但实际上,这款硬件在Windows 10环境下可以变身为强大的网络诊断利器。本文将带你探索…...
实战演练企业级mysql环境搭建,快马平台生成电商项目配置全流程
今天想和大家分享一个企业级MySQL环境搭建的实战经验。最近在帮朋友搭建一个电商网站的后台数据库,正好用到了InsCode(快马)平台来快速生成配置方案,整个过程非常顺畅。 1. 准备工作与环境选择 首先需要明确的是,企业级MySQL部署和本地开发…...
2025最权威的AI论文助手推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在当下诸多处于主流地位的AI论文工具当中,Grammarly于语法校对以及学术表达优化…...
win-acme证书自动续期架构深度解析:从故障排查到高可用部署
win-acme证书自动续期架构深度解析:从故障排查到高可用部署 【免费下载链接】win-acme Automate SSL/TLS certificates on Windows with ease 项目地址: https://gitcode.com/gh_mirrors/wi/win-acme 技术背景与挑战 在当今云原生和微服务架构盛行的时代&am…...
FPGA调试:除了SignalTap,你更应该试试Quartus自带的这个免费“信号发生器+逻辑分析仪”
FPGA调试实战:Quartus自带的轻量级调试利器In-System Sources and Probes Editor 在FPGA开发中,调试环节往往占据项目周期的半壁江山。当SignalTap II这类逻辑分析仪因资源占用过高而显得"杀鸡用牛刀"时,许多工程师会陷入两难——既…...
FixPlus-v1.56.148 一键擦除,会员功能直接解锁
核心功能 AI智能擦除技术可精准识别并移除照片中的干扰元素(如路人、杂物),自动填补背景,处理效果自然无痕。AI换衣功能支持智能服装替换与风格调整,为创意编辑提供更多可能。 操作便捷性 无需专业技巧,通…...
