当前位置: 首页 > news >正文

Android流式布局FlowLayout

自定义viewGroup实现流式布局

packagecom.example.flowlayout;importandroid.content.Context;importandroid.content.res.Resources;importandroid.util.AttributeSet;importandroid.util.Log;importandroid.util.TypedValue;importandroid.view.View;importandroid.view.ViewGroup;importjava.util.ArrayList;importjava.util.List;publicclassFlowLayoutextendsViewGroup{// item的横向、纵向间距,可以通过xml,在构造方法中设置privateintmHorizationSpacing=dp2px(16);privateintmVerticalSpacing=dp2px(8);privateList<List<View>>allViews=newArrayList<>();// 所有的行privateList<Integer>lineHeightList=newArrayList<>();// 每一行的行高publicFlowLayout(Contextcontext){super(context);}publicFlowLayout(Contextcontext,AttributeSetattrs){super(context,attrs);}publicFlowLayout(Contextcontext,AttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);}publicFlowLayout(Contextcontext,AttributeSetattrs,intdefStyleAttr,intdefStyleRes){super(context,attrs,defStyleAttr,defStyleRes);}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){super.onMeasure(widthMeasureSpec,heightMeasureSpec);Log.e("flowlayout","onMeasure ===== ");clearMeasureParams();intchildCount=getChildCount();intpl=getPaddingLeft();intpr=getPaddingRight();intpt=getPaddingTop();intpb=getPaddingBottom();intselfWidth=MeasureSpec.getSize(widthMeasureSpec);intselfHeight=MeasureSpec.getSize(heightMeasureSpec);intselfNeedWidth=0;intselfNeedHeight=0;List<View>lineView=newArrayList<>();intlineUsedWhidth=0;intlineHeight=0;for(inti=0;i<childCount;i++){Viewchild=getChildAt(i);LayoutParamschildLayoutParams=child.getLayoutParams();// 将LayoutParams转换为子view的MeasureSpecintchildWidthMeasureSpec=getChildMeasureSpec(widthMeasureSpec,pl+pr,childLayoutParams.width);intchildHeightMeasureSpec=getChildMeasureSpec(heightMeasureSpec,pt+pb,childLayoutParams.height);// 分发给子view测量child.measure(childWidthMeasureSpec,childHeightMeasureSpec);// 测量完后就可以获得子view的宽高intchildMeasuredWidth=child.getMeasuredWidth();intchildMeasuredHeight=child.getMeasuredHeight();// 换行if(lineUsedWhidth+mHorizationSpacing+childMeasuredWidth+pl+pr>selfWidth){// 已经有的存储allViews.add(lineView);lineHeightList.add(lineHeight);// 保存数据selfNeedWidth=Math.max(selfNeedWidth,lineUsedWhidth+mHorizationSpacing);selfNeedHeight+=lineHeight+mVerticalSpacing;lineView=newArrayList<>();lineUsedWhidth=0;lineHeight=0;}// 流式布局,需要存放每一行已用的宽、当前行中最高值lineView.add(child);lineUsedWhidth+=childMeasuredWidth+mHorizationSpacing;lineHeight=Math.max(childMeasuredHeight,lineHeight);// 判断是否是最后一行if(i==childCount-1){// 已经有的存储allViews.add(lineView);lineHeightList.add(lineHeight);// 保存数据selfNeedWidth=Math.max(selfNeedWidth,lineUsedWhidth+mHorizationSpacing);selfNeedHeight+=lineHeight+mVerticalSpacing+pb+pt;}}intwidthMode=MeasureSpec.getMode(widthMeasureSpec);intheightMode=MeasureSpec.getMode(heightMeasureSpec);intrealWidth=widthMode==MeasureSpec.EXACTLY?selfWidth:selfNeedWidth;intrealHeight=heightMode==MeasureSpec.EXACTLY?selfHeight:selfNeedHeight;// 再测量自己的宽高setMeasuredDimension(realWidth,realHeight);}privatevoidclearMeasureParams(){allViews.clear();lineHeightList.clear();}@OverrideprotectedvoidonLayout(booleanchanged,intl,intt,intr,intb){Log.e("flowlayout","onLayout ===== ");intlineCount=allViews.size();intpaddingLeft=getPaddingLeft();intpaddingTop=getPaddingTop();for(inti=0;i<lineCount;i++){for(Viewview:allViews.get(i)){intleft=paddingLeft;inttop=paddingTop;intright=left+view.getMeasuredWidth();intbottom=top+view.getMeasuredHeight();view.layout(left,top,right,bottom);paddingLeft=right+mHorizationSpacing;}// 一行结束后,下一行的高paddingTop+=lineHeightList.get(i)+mVerticalSpacing;paddingLeft=getPaddingLeft();}}publicstaticintdp2px(intdp){return(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,Resources.getSystem().getDisplayMetrics());}}

在xml中使用

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><com.example.flowlayout.FlowLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_500"android:padding="15dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="洗脸巾"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="相机"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="化妆水"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="邮箱贴纸"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="移ddddd"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="z"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="数据"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text=""/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text=""/><TextViewandroid:layout_width="wrap_content"android:layout_height="50dp"android:background="@color/purple_200"android:padding="5dp"android:text="手机保护壳"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="手机充电线"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="5dp"android:text="实测中"/></com.example.flowlayout.FlowLayout></LinearLayout>
http://www.cnnetsun.cn/news/2494602.html

相关文章:

  • 如何快速配置Live Server Web Extension:提升开发效率的完整指南
  • 4大核心功能解析:Bifrost跨平台三星固件管理工具的革新之道
  • 一键预览文件夹:Windows文件管理的终极效率革命
  • 【芳心科技】F. 基于STM32的MPPT光伏控制器设计
  • 三步掌握LeagueAkari:英雄联盟玩家的智能游戏助手终极指南
  • 超现实提示词失效真相:37个被低估的语义锚点与21种跨模态干扰源(含CLIP文本嵌入热力图)
  • 如何快速掌握Vant Weapp:面向小程序开发者的完整组件库指南
  • 如何使用Python和TensorFlow Lite实现高效人脸检测与面部特征分析
  • Windows USB设备网络共享解决方案:usbipd-win深度技术指南
  • 35岁程序员的AI突围战:掌握这三条路径,让AI成为你的“不可替代”武器,收藏这波干货!
  • Windows Subsystem for Linux GUI (WSLg) 终极指南:让Linux图形应用在Windows上完美运行
  • 3分钟掌握Wallpaper Engine创意工坊下载器:告别繁琐命令行的动态壁纸神器
  • 10分钟搞定黑苹果:OpCore-Simplify自动化配置工具完全指南
  • Burp Suite绕过验证码实战:无需OCR的逻辑绕过方法
  • 3步解决Buzz语音转文字工具Faster Whisper模型下载失败问题
  • QMCDecode:macOS上QQ音乐加密文件的终极解密指南
  • 从 0 打造 99.99% 在线 CRM——实战复盘多活部署、CDN 加速与边缘缓存全链路优化
  • 如何3分钟安装B站成分检测器:一键识别评论区用户真实身份
  • 自由学习记录(189)
  • douyin-downloader:构建企业级抖音内容资产管理平台的技术架构与实践
  • Minecraft多版本管理的终极解决方案:Prism Launcher深度解析
  • 易久批x-sign参数逆向分析
  • DySample:解决密集预测任务中动态上采样性能瓶颈的高效架构优化方案
  • 新手教程使用Python快速调用Taotoken平台上的大模型API
  • Vue开发必看:存储技巧+AI避坑+性能优化全攻略
  • ElevenLabs马来语语音生成失效真相(92%开发者忽略的ISO 639-3语言码陷阱)
  • 【权威实测报告】:在137组对比测试中,仅2组prompt达成Apple Human Interface Guidelines认证级毛玻璃效果(附完整prompt审计清单)
  • 无人值守智慧仓库管理系统:工单自动比对,实现领料全流程无人化
  • CameraFileCopy:无需网络,用摄像头实现手机间文件传输的创新方案
  • 聊天功能不需要额外申请其他证件什么的