Android自定义ViewGroup自动分配子view位置
2015-12-03 13:01
766 查看
子布局的view的宽高是wrap属性,功能是自动分配子view的位置, 具有自动换行,水平居中的功能
图示
代码
import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import com.magus.trainingfirstapp.utils.DisplayUtil; /** * Created by yangshuai in the 17:25 of 2015.12.02 . * 自动分配子view的位置, 具有自动换行,水平居中的功能 */ public class AutoDisplayChildViewContainer extends ViewGroup { private int parentWidth; private int totaleft = 0; private int totalTop = 0; private int margin = 10; private int maxChildHeight = 0; private int totalRight = 0; public AutoDisplayChildViewContainer(Context context) { super(context); } public AutoDisplayChildViewContainer(Context context, AttributeSet attrs) { super(context, attrs); } public AutoDisplayChildViewContainer(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /* 测量父布局 */ parentWidth = measureSize(widthMeasureSpec, DisplayUtil.dip2px(getContext(), 240)); int count = getChildCount(); int tempMaxChildHeight = 0; int tempTotalHeight = 0; int tempTotalRight = 0; for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child.getVisibility() != View.GONE) { /* 测量子布局 */ if (child.getMeasuredWidth() > parentWidth) { child.measure(parentWidth, child.getMeasuredHeight()); } else child.measure(child.getMeasuredWidth(), child.getMeasuredHeight()); tempMaxChildHeight = Math.max(tempMaxChildHeight, child.getMeasuredHeight()); tempTotalRight += child.getMeasuredWidth(); if (tempTotalRight > parentWidth) { tempTotalHeight += tempMaxChildHeight; tempMaxChildHeight = child.getMeasuredHeight(); tempTotalRight = child.getMeasuredWidth(); } } } /* 获取适配子布局后的高度 */ int parentHeight = tempTotalHeight + tempMaxChildHeight + margin; setMeasuredDimension(parentWidth, parentHeight); } private int measureSize(int measureSpec, int defaultSize) { int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); int result = defaultSize; if (mode == MeasureSpec.EXACTLY) { result = size; } else if (mode == MeasureSpec.AT_MOST) { result = Math.max(size, result); } return result; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int count = getChildCount(); int lineViewCount = 0; for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child.getVisibility() != View.GONE) { if (i != 0) { /* child 的 left 是上个子 view 的宽加上 margin */ totaleft += getChildAt(i - 1).getMeasuredWidth() + margin; } else { totaleft = 0; totalTop = 0; maxChildHeight = child.getMeasuredHeight(); } /* child 的 right */ totalRight = totaleft + child.getMeasuredWidth(); /* 如果 rigth 大于 父布局的宽, 则换行 */ if (totalRight > parentWidth) { adjustLine(lineViewCount, i); // 调整这一行的子布局的位置 lineViewCount = 0; // 这一行的子 child 的数量充值 totalTop += maxChildHeight; totaleft = 0; maxChildHeight = child.getMeasuredHeight(); totalRight = child.getMeasuredWidth(); }else { maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); } child.layout( totaleft, totalTop, totalRight, totalTop + child.getMeasuredHeight() ); /* 统计这一行的子view的数量 */ lineViewCount++; } } /* 调整最后一行子布局的位置 */ totaleft = totalRight + margin; adjustLine(lineViewCount, count); } /* 调整一行,让这一行的子布局水平居中 */ private void adjustLine(int lineViewCount, int i) { totaleft = (parentWidth - totaleft) / 2; int marginTop; for (int lineViewNumber = lineViewCount; lineViewNumber > 0; lineViewNumber--) { View lineViewChild = getChildAt(i - lineViewNumber); totalRight = totaleft + lineViewChild.getMeasuredWidth(); if (lineViewChild.getMeasuredHeight() != maxChildHeight) { marginTop = (maxChildHeight - lineViewChild.getMeasuredHeight()) / 2; } else { marginTop = 0; } lineViewChild.layout(totaleft, totalTop + marginTop, totalRight, totalTop + marginTop + lineViewChild.getMeasuredHeight()); totaleft += lineViewChild.getMeasuredWidth() + margin; } } }
github
https://github.com/Afra55/TrainingFirstApp相关文章推荐
- Android第三方开源NiftyNotification(Android Toast替代品):动画效果生动有趣的通知
- Android源码--程序的分享、卸载、启动及详细信息
- Android 编程下 Touch 事件的分发和消费机制
- Android源码--多击事件
- Android学好Shape不再依赖美工
- 利用Android属性动画实现Banner控件
- Android编译系统入门(一)
- Android 带分隔符的EditText
- 《疯狂Android讲义》学习笔记二
- Android--屏幕适配
- Android编程之动态壁纸实例分析
- 【FastDev4Android框架开发】Android Design支持库TabLayout打造仿网易新闻Tab标签效果(三十七)
- Android SQLite数据库增删改查操作的使用详解
- Android编程之自定义锁屏实例分析
- android中Gson类库的使用
- Android XML 预览卡至死
- android 取消edittext焦点
- Android ANR 分析解决方法
- Android设置Settings:ListPreference【3】
- Android Socket 与 IOS Socket