Android 流式布局
2015-09-18 17:52
411 查看
后附源码地址
思路:
1、自定义View;
2、由于这个View是要包含其他控件,所以继承ViewGroup;
3、设置这个自定义View的LayoutParams,重写generateLayoutParams,这里设置的是MarginLayoutParams;
4、重写OnMeasure,计算该容器的大小和子元素的大小
5、重写OnLayout,设置子控件的位置
这里需要注意:该空间的模式
**warp_content: MeasureSpec.AT_MOST 需要根据子布局的大小设置该控件的大小。
fill_parent和mach_parent:MeasureSpec.EXACTLY 直接使用获取大小即可**
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
FlowView.java
package com.ucloud.oxpecker.views; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class FlowView extends ViewGroup { public FlowView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public FlowView(Context context, AttributeSet attrs) { super(context, attrs); } public FlowView(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); // warp_content int width = 0, height = 0, lineWidth = 0, lineHeight = 0; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); MarginLayoutParams params = (MarginLayoutParams) child .getLayoutParams(); int childWidth = child.getMeasuredWidth() + params.leftMargin + params.rightMargin; int childHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin; if (childWidth + lineWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) { // 对比得到最大宽度 width = Math.max(lineWidth, width); // 重置lineWidth lineWidth = childWidth; // 记录行高 height += lineHeight; lineHeight = childHeight; } else { lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); } if (i == getChildCount() - 1) { width = Math.max(lineWidth, width); height += lineHeight; } } setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width + getPaddingLeft() + getPaddingRight(), modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom()); } private List<List<View>> mAllViews = new ArrayList<List<View>>(); // 每一行的高度 private List<Integer> mLineHeight = new ArrayList<Integer>(); // 每一行距离左边的距离 private List<Integer> mLineMarginLeft = new ArrayList<Integer>(); @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mAllViews.clear(); mLineHeight.clear(); int width = getMeasuredWidth(); int lineWidth = 0, lineHeight = 0; List<View> lineViews = new ArrayList<View>(); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); MarginLayoutParams params = (MarginLayoutParams) child .getLayoutParams(); int childWidth = child.getMeasuredWidth() + params.leftMargin + params.rightMargin; int childHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin; if (childWidth + lineWidth > width - getPaddingLeft() - getPaddingRight()) { // 计算每行距离左边距离 int lineLeftMargin = (width - lineWidth) / 2; mLineMarginLeft.add(lineLeftMargin); // 行高 mLineHeight.add(lineHeight); mAllViews.add(lineViews); lineWidth = 0; lineHeight = childHeight; lineViews = new ArrayList<View>(); } lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); lineViews.add(child); } /** 处理最后一行 **/ // 计算每行距离左边距离 int lineLeftMargin = (width - lineWidth) / 2; mLineMarginLeft.add(lineLeftMargin); // 行高 mLineHeight.add(lineHeight); mAllViews.add(lineViews); /** 设置子View的位置 **/ int left = getPaddingLeft(), top = getPaddingTop(); for (int i = 0; i < mAllViews.size(); i++) { lineViews = mAllViews.get(i); lineHeight = mLineHeight.get(i); // 居中显示的左边距 left += mLineMarginLeft.get(i); for (int j = 0; j < lineViews.size(); j++) { View child = lineViews.get(j); if (child.getVisibility() == View.GONE) continue; MarginLayoutParams params = (MarginLayoutParams) child .getLayoutParams(); int lc = left + params.leftMargin; int tc = top + params.topMargin; int rc = lc + child.getMeasuredWidth(); int bc = tc + child.getMeasuredHeight(); child.layout(lc, tc, rc, bc); left += child.getMeasuredWidth() + params.leftMargin + params.rightMargin; } left = getPaddingLeft(); top += lineHeight; } } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } }
调用方式
FlowView flowViewRecive = (FlowView) findViewById(R.id.flowView_recive); flowView.removeAllViews(); AttrTextView tv = new AttrTextView(this); MarginLayoutParams lp = new MarginLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); tv.setText("测试"); lp.leftMargin = 10; lp.rightMargin = 10; lp.topMargin = 5; lp.bottomMargin = 5; tv.setBackgroundResource(R.drawable.shape_tv_email); tv.setTextColor(getResources().getColor(R.color.black)); flowView.addView(tv, lp);
源码下载
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories