android 流式布局简单实现
来源:互联网 发布:爱口袋软件下载 编辑:程序博客网 时间:2024/05/24 01:50
1.概述
今天看了Android自定义控件的书籍之后准备动手写个自定义控件,于是有了该篇文章。之前也看过一些大神们写的,受益匪浅。初写博客一方面是想向大神们学习,另一方面也算是自己学习的一个记录。
2.思路分析
好了废话不多扯,开始正题:流式布局肯定一个view容器也就是ViewGroup。从View的工作原理可以得知 View的绘制流程:
onMeasure —–> onLayout —–> onDraw,依次是
测量规格 —-> 确定位置 —> 绘制。 因此我们实现流式布局只需要重写前2步,即onMeasure和onLayout。
测量时需要通常需要处理测量模式为AT_MOST 对应wrap_content,这种情况需要根据子控件的宽和高来最终确认父控件的宽和高。
3.代码实现
public class FlowView extends ViewGroup { public FlowView(Context context) { this(context, null); } public FlowView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FlowView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int measureWidth = 0; int measureHeight = 0; int childCount = getChildCount(); int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec); int measureWidthSize = MeasureSpec.getSize(widthMeasureSpec); int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec); int measureHeightSize = MeasureSpec.getSize(heightMeasureSpec); /**note: 原本写法先判断 Mode 都是Exactly的情况下不去测量 childView,从而提高效率。 * 针对onMeasure是可以的,但是onLayout中需要获取子控件width和height 时 * 还是得测量,所以此处统一测量了。 * */ //if (measureHeightMode == MeasureSpec.EXACTLY //&& measureWidthMode == MeasureSpec.EXACTLY) { // measureWidth = measureWidthSize; // measureHeight = measureHeightSize; //} else { for (int i = 0; i < childCount; i++) { View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); MarginLayoutParams layoutParam = (MarginLayoutParams) child.getLayoutParams(); int cWidth = child.getMeasuredWidth() + layoutParam.leftMargin + layoutParam.rightMargin; int cHeight = child.getHeight() + layoutParam.topMargin + layoutParam.bottomMargin; /** * 思路:不换行--> width累加 height取max * 换行 --> width = 上一行累加值与当前控件width的 max值 * height = 上一行的max值 + 当前控件的height */ if (measureWidth + cWidth > measureWidthSize) { measureWidth = Math.max(measureWidth, cWidth); measureHeight += cHeight; } else { measureHeight = Math.max(measureHeight, cHeight); measureWidth += cWidth; } } setMeasuredDimension(measureWidthMode == MeasureSpec.EXACTLY ? measureWidthSize : measureWidth, measureHeightMode == MeasureSpec.EXACTLY ? measureHeightSize : measureHeight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int lineWidth = 0; int lineHeight = 0; int left = 0; int top = 0; for (int i = 0; i < childCount; i++) { View child = getChildAt(i); MarginLayoutParams layoutParam = (MarginLayoutParams) child.getLayoutParams(); int cWidth = child.getWidth() + layoutParam.leftMargin + layoutParam.rightMargin; int cHeight = child.getHeight() + layoutParam.topMargin + layoutParam.bottomMargin; //换行 if (cWidth + lineWidth > getWidth()) { if (child.getVisibility() != View.GONE) { left = 0; top = lineHeight; child.layout(left + layoutParam.leftMargin, top + layoutParam.topMargin, left + layoutParam.leftMargin + child.getMeasuredWidth(), top + layoutParam.topMargin + child.getMeasuredHeight()); left += layoutParam.leftMargin + child.getMeasuredWidth(); } lineWidth = cWidth; lineHeight += cHeight; } else { lineWidth += cWidth; lineHeight = Math.max(lineHeight, cHeight); if (child.getVisibility() != View.GONE) { child.layout(left + layoutParam.leftMargin, top + layoutParam.topMargin, left + layoutParam.leftMargin + child.getMeasuredWidth(), top + layoutParam.topMargin + child.getMeasuredHeight()); left += layoutParam.leftMargin + child.getMeasuredWidth(); } } } } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); }}
4.运行测试
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <demos.ch.com.flowlayout.FlowView android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button style="@style/btn_style" android:text="演员" /> <Button style="@style/btn_style" android:text="你还要我怎样" /> <Button style="@style/btn_style" android:text="方圆几里" /> <Button style="@style/btn_style" android:text="绅士" /> <Button style="@style/btn_style" android:text="认真的雪" /> <Button style="@style/btn_style" android:text="faded" /> <Button style="@style/btn_style" android:text="We dont talk more" /> <Button style="@style/btn_style" android:text="Jar of love" /> <Button style="@style/btn_style" android:text="可惜没如果" /> <Button style="@style/btn_style" android:text="浪费" /> <Button style="@style/btn_style" android:text="一丝不挂" /> <Button style="@style/btn_style" android:text="阴天快乐" /> <Button style="@style/btn_style" android:text="可以了" /> </demos.ch.com.flowlayout.FlowView></LinearLayout><---样式文件 ---><style name="btn_style"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_margin">5dp</item> <item name="android:background">@color/colorBackground</item> <item name="android:textColor">#ffffff</item> <item name="android:textSize">24dp</item> </style>
运行结果:
1.match_parent | wrap_content
2.固定值(400dp)
以上就实现了简单的流式布局实现。
源码下载:
[https://github.com/ChenHaoLw/FlowLayout]
1 0
- Android流式布局的简单实现
- Android流式布局的简单实现
- android 流式布局简单实现
- Android 简单实现流式布局
- Android流式布局实现
- Android流式布局实现
- Android流式布局实现
- Android流式布局实现
- 实现Android流式布局
- Android开发学习之卡片式布局的简单实现
- Android开发学习之卡片式布局的简单实现
- Android卡片式布局的简单实现方法
- 简单实现响应式布局
- Android之路-简单布局的实现
- Android RecyclerView加载不同布局简单实现
- Android 简单 相对布局的实现;
- Android 流式布局实现方法
- Android 流式布局实现方法
- ThreadPoolExecutor 队列缓存策略
- 汇编作业
- I2C、SPI、USRT、USRAT通信方式对比
- ACM中java的使用
- python读取、写入csv数据:csv模块
- android 流式布局简单实现
- 10.数据库命令操作 runCommand()
- android 请求工具FinalHttp和HttpUtils的一个区别
- mac vim下的批量缩进
- 从linux 系统调用 学习可变参数宏的用法
- 非常实用的C# backgroundworker使用方法
- Ubuntu14安装pcl点云库
- 获取IP地址
- RegExp对象方法