Android最简洁的自动换行布局组件

2023-11-18

自动换行是一种布局特性,理所当然应该在布局组件中实现。

我们基于ViewGroup实现了最简洁和稳定的自动换行布局组件AutoLinefeedLayout。该组件无需特别设置,只要将孩子塞给它,就会自动换行显示,无任何限制。

源码如下:


package melandru.android.sdk.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class AutoLinefeedLayout extends ViewGroup {

	public AutoLinefeedLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public AutoLinefeedLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public AutoLinefeedLayout(Context context) {
		this(context, null);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		layoutHorizontal();
	}

	private void layoutHorizontal() {
		final int count = getChildCount();
		final int lineWidth = getMeasuredWidth() - getPaddingLeft()
				- getPaddingRight();
		int paddingTop = getPaddingTop();
		int childTop = 0;
		int childLeft = getPaddingLeft();

		int availableLineWidth = lineWidth;
		int maxLineHight = 0;

		for (int i = 0; i < count; i++) {
			final View child = getChildAt(i);
			if (child == null) {
				continue;
			} else if (child.getVisibility() != GONE) {
				final int childWidth = child.getMeasuredWidth();
				final int childHeight = child.getMeasuredHeight();

				if (availableLineWidth < childWidth) {
					availableLineWidth = lineWidth;
					paddingTop = paddingTop + maxLineHight;
					childLeft = getPaddingLeft();
					maxLineHight = 0;
				}
				childTop = paddingTop;
				setChildFrame(child, childLeft, childTop, childWidth,
						childHeight);
				childLeft += childWidth;
				availableLineWidth = availableLineWidth - childWidth;
				maxLineHight = Math.max(maxLineHight, childHeight);
			}
		}
	}

	private void setChildFrame(View child, int left, int top, int width,
			int height) {
		child.layout(left, top, left + width, top + height);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		int count = getChildCount();
		for (int i = 0; i < count; i++) {
			measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
		}
		if (heightMode == MeasureSpec.AT_MOST||heightMode == MeasureSpec.UNSPECIFIED) {
			final int width = MeasureSpec.getSize(widthMeasureSpec);
			super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
					getDesiredHeight(width), MeasureSpec.EXACTLY));
		} else {
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		}
	}

	private int getDesiredHeight(int width) {
		final int lineWidth = width - getPaddingLeft() - getPaddingRight();
		int availableLineWidth = lineWidth;
		int totalHeight = getPaddingTop() + getPaddingBottom();
		int lineHeight = 0;
		for (int i = 0; i < getChildCount(); i++) {
			View child = getChildAt(i);
			final int childWidth = child.getMeasuredWidth();
			final int childHeight = child.getMeasuredHeight();
			if (availableLineWidth < childWidth) {
				availableLineWidth = lineWidth;
				totalHeight = totalHeight + lineHeight;
				lineHeight = 0;
			}
			availableLineWidth = availableLineWidth - childWidth;
			lineHeight = Math.max(childHeight, lineHeight);
		}
		totalHeight = totalHeight + lineHeight;
		return totalHeight;
	}

}

国际惯例

—————————————————————————————————————————————————————————————————————————————

作者:

薄荷记账     优秀源码探索者     简洁   稳定   优雅   无限可能!

转载请注明作者信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android最简洁的自动换行布局组件 的相关文章

  • appcompat_v7 错误

    我发现材料支持库 更新的 appcompat v7 将于 10 月 17 日推出 http www reddit com r androiddev comments 2jd5gl roman nurik material support l
  • Android CirclePageIndicator 不工作

    我无法使用 CirclePageIndicator 加载页面 这是 XML
  • Android x86_64 和 x86 模拟器在 AlertDialog.onClick 事件上崩溃

    我正在 x86 64 和 x86 模拟器中测试 Android 应用程序 在从显示列表的 AlertDialog 中选择一个项目后 它崩溃了 Android 模拟器意外关闭 AlertDialog 是从 AppCompatActivity
  • MaterialComponents AlertDialog 文本颜色

    Reading MaterialComponents 主题警报对话框按钮 https stackoverflow com questions 52829954 materialcomponents theme alert dialog bu
  • 在 CollapsingToolbarLayout 中设置 minHeight 没有任何效果

    我目前使用 CollapsingToolbarLayout 遇到的主要问题是 无论我尝试什么 工具栏的 minHeight 属性都没有任何效果 我想要的结果是这样的 CollapsingToolbarLayout 具有一定的展开高度和一定的
  • 无法在 Android 模拟器上使用 ART

    我只是想在我的模拟器上尝试 android 4 4 的 ART 我所做的是创建一个模拟器 选择设备为 Nexus 7 目标为 Android 4 4 RAM 512 然后我启动模拟器并加载它 然后我进入开发者选项并选择运行时作为 ART 设
  • 从 DecorView@2da7146[MyActivity] 中找不到 ViewTreeLifecycleOwner

    从撰写更新后alpha 11 to alpha 12 or beta 01 每当我打开具有撰写视图的活动或片段时 我都会遇到此崩溃 我在用AppCompatActivity它实现了LifecycleOwner 所以这非常奇怪 java la
  • FFmpeg 不适用于 android 10,直接进入 onFailure(String message) 并显示空消息

    我在我的一个项目中使用 FFmpeg 进行视频压缩 在 Android 10 Google Pixel 3a 上 对于发送执行的任何命令 它会直接进入 onFailure String message 并显示空消息 所以我在我的应用程序 g
  • java.lang.RuntimeException:release()后调用的方法

    If i am 不使用 相机 release in 表面被破坏 then 无法从另一个 Activity 再次启动 CameraActivity 简而言之 得到不幸的是应用程序已停止 错误 即使不释放相机 但如果我确实点击了 主页 按钮 来
  • Android 6.0 缺乏访问相机服务的权限

    我在 Android 6 0 中使用 Camera2API 我在Android 5 0中没有报错 然而 当我在 Android 6 0 中使用我的代码时 我遇到了问题 问题是有时我可以成功打开相机并拍照 但有时相机打不开 出现错误 java
  • 自定义 ListView 具有不同的行布局,根据 Web 服务响应进行扩展

    我有列表视图 我有3组观点 图像视图 视频查看 文本视图 我有一个返回图像 视频和文本的网络服务器 因此 根据服务器的响应 我想膨胀列表视图中行的视图 我知道使用自定义适配器来扩展自定义布局 我想知道如何使用自定义适配器来扩充视图类型 例如
  • 使用 firebase 按最新消息对聊天列表进行排序

    我不知道为什么我陷入了一个问题chatList不按最后一条消息时间或最新消息排序 我尝试过存储timestamp在数据库中和订单子依据时间戳 但它仍然不起作用 不起作用意味着列表不会在每条消息后排序 并继续将列表显示为在第一条消息后排序 看
  • 错误:包 com.google.android.gms.appstate 不存在

    由于此错误 无法编译我的 android 项目 BaseGameUtils src main java com google example games basegameutils GameHelper java Error 32 39 e
  • 在多模块项目中访问绑定适配器

    我有一个多模块项目 其中应用程序模块包含我的绑定适配器 而我的功能模块取决于我的应用程序模块 因为它是动态功能模块 应用程序 包含绑定适配器 gt 动态功能模块 存在布局的地方 我在所有模块中启用了数据绑定和 kapt 我无法成功构建应用程
  • 如何在Android data/data/project文件系统中创建文件目录和文件夹

    我正在开发一个视频编辑器程序 并且对 android 和 java 相当陌生 我希望发生的是 当用户按下 创建新项目 按钮时 会弹出一个对话框 询问用户项目的名称 我已经把那部分写下来了 但是我想要的是 当用户在该对话框上按 确定 时 我的
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO
  • DialogFragment在Android中的位置

    我有一个DialogFragment显示一个View就像弹出屏幕一样 窗口始终出现在屏幕中间 有没有办法设置位置DialogFragment窗户 我已经查看了但还没有找到任何东西 尝试这样的事情 Override public View o
  • 在运行时用Dagger添加Retrofit RequestInterceptor

    我正在使用匕首和改装 我用 Dagger 注入我的 Retrofit 服务 现在我想做一个授权请求来获取 accessToken 之后 我想使用请求拦截器来增强我的 api 模块 以便将此访问令牌用于将来的请求 我的想法是在收到访问令牌后使
  • 如何从耳机插孔获取电力?

    我的问题是是否有人知道如何创建一个可以通过设备的耳机插孔发送电荷的 Android 应用程序 就像这个视频中那样 该视频展示了一款 iPhone 应用程序 可控制插入耳机插孔的 LED 我想知道如何访问该设备来发送电信号 抱歉我的英语不是我
  • Android 方向传感器的替代品是什么?

    大家好 我正在为 Android 构建 3D 游戏 我目前正在尝试在我的游戏中添加一个传感器 允许玩家倾斜机器人作为其控制 理想情况下 我想使用方向传感器 但我注意到它已被弃用 有谁知道如何检测 Android 中的倾斜并且不使用这个传感器

随机推荐

  • selenium和Firefox geckodriver的安装

    安装selenium 首先你安装了python并设置了环境变量 直接win r输入cmd 进入命令行 然后输入 pip install selenium i https pypi tuna tsinghua edu cn simple 安装
  • Tomcat默认日志路径修改

    Tomcat安装目录下Logs目录下默认会产生4种日志文件 catalina log host manager log localhost log manager log 系统出现异常的时候 有时候log文件会暴涨 这里偶是把日志文件移动到
  • npm run dev 报错:missing script:dev

    报错信息 报错原因 package json 里面没有 scripts dev xxx 这段了 解决方法
  • 七牛云的使用(图片超详讲解)

    一 为什么要使用七牛云的OSS 对象存储服务 二 七牛云使用 登录七牛云官网 注册并认证 初次认证有30天免费使用权限 新建存储空间 点击创建的空间名字 进入 空间概括如下 阅读帮助文档 在自己的web应用中 使用七牛云对象存储服务OSS
  • 多态反射机制

    package duotai class Customer SuppressWarnings unused private String account SuppressWarnings unused private String pass
  • word怎么删除最后一页空白页

    1 将光标移动到最后一页的起始处 不停的按删除键 gt 我试了 无效 2 将光标定位在倒数第二页的末尾 直接按delete键进行删除 或者可以试试按住ctrl键再按delete键 gt 我试了 还是无效 3 将光标移动到最后一页 在菜单栏找
  • 答辩经验

    例举几个问题作为参考 给大家分析一些常见问题的回答注意点以及技巧 通过这几个问题的讲解告诉大家如何为答辩做准备 主要是讲一个方式方法 起一个抛砖引玉的作用 您了解之后可以针对自己的设计做相应的准备 1 你选这个课题的意义是什么呢 这个问题非
  • pandas 解决 A value is trying to be set on a copy of a slice from a DataFrame的问题

    stackoverflow 解决方案链接 https stackoverflow com questions 31468176 setting values on a copy of a slice from a dataframe rq
  • 微信小程序【发送给朋友】和【复制链接】功能,灰色不可用

    每日鸡汤 悲观者可能正确 但是乐观者往往成功 假设你是一个用户 你随便找一个小程序可以看到这几个功能 转发给朋友 分享到朋友圈 复制链接 很常见的功能 但是如果你作为开发者 这几个功能就需要自己做喽 并不是你项目建起来了就有的 1 转发给朋
  • 软实力-领导力

    领导力 领导力不是一蹴而就 需要不断训练和提炼 团队也是需要不断发展和规划 一个普通员工如何才能具备领导力呢 俗话说 天上不会掉馅饼 即使偶尔掉个馅饼下来 你的嘴也需要比别人的嘴张得大才能吃到 这 儿的嘴大可能包括你的能力和为这件事做的准备
  • echarts 图设置高度_Echarts 自适应宽高 vue

    思路 1 将图表包括在一个div中 该div设置了固定的宽高 可为百分比 2 由于不能直接设置rem进行适配 需要动态计算出 id chart 的高度 setChartHeight 根据自己需要调节图形大小 我的图形是放在 中 let ma
  • Golang获取当日00:00:00时间戳

    遇到好几次这个问题了 go的time里也没有这东西 百度也搜不到 很烦 干脆自己写一份 放到这里 year month day time Now Date location time LoadLocation Asia Shanghai 这
  • ESD 接触放电、空气放电

    1 接触放电主要针对的是半成品电子电气产品 或者是带金属外壳的成品 一般做接触放电主要是金属外壳 接触放电的放电头是尖头 2 空气放电主要是针对塑料外壳或者是金属外壳表面有绝缘漆的成品 空气放电的放电头是圆形头 3 一般接触放电或者空气放电
  • Python 之父 Guido van Rossum 称退休太无聊,正式加入微软搞开源!

    参考 https blog csdn net sinat 14921509 article details 109667079
  • 产品养成记

    参与感 pdf 从零开始做运营入门篇 张亮 pdf 结网 pdf 精益创业 pdf 区块链 定义未来金融与经济新格局 pdf 区块链 从数字货币到信用社会 pdf 人人都是产品经理 pdf 如何阅读一本书 pdf 上瘾 pdf 数据分析实战
  • 阿里云ACP级认证考试心得+过关经验

    正在准备阿里云ACP级认证考试的童鞋福利来啦 经过小编的软磨硬泡 终于从高分通过ACP云计算专业认证及大数据专业认证的大牛同事那里要来了考试心得 经验分享 直接看吧 认证考试简介 知己知彼知大纲 首先介绍一下ACP考试 阿里云认证类似于大家
  • flutter Text数字超出全部隐藏 解决方法

    如图 刚开始是这样的 问题原因 前面的 ID 与后面的文字存在间隙 解决方法 修改前 child Text ID 1114954321 textAlign TextAlign right maxLines 1 overflow TextOv
  • 切面打印日志时,参数序列化异常。It is illegal to call this method if the current request is not in asynchron

    1 AOP的日志拦截类中 抛出异常 2 代码如下 package com jimulian iwuxi common aop import com alibaba fastjson JSON import com jimulian iwux
  • 华为OD机试真题-增强的strstr-2023年OD统一考试(B卷)

    题目描述 C 语言有一个库函数 char strstr const char haystack const char needle 实现在字符串 haystack 中查找第一次出现字符串 needle 的位置 如果未找到则返回 null 现
  • Android最简洁的自动换行布局组件

    自动换行是一种布局特性 理所当然应该在布局组件中实现 我们基于ViewGroup实现了最简洁和稳定的自动换行布局组件AutoLinefeedLayout 该组件无需特别设置 只要将孩子塞给它 就会自动换行显示 无任何限制 源码如下 pack