Android自定义ViewGroup-入门
1.效果

2步骤
自定义ViewGroup的步骤是
1.1测量onMeasure
/**
* 获取子view的个数
* 逐个测量其宽高 得到整个ViewGroup的宽高
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取流式布局的宽度和模式
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
//获取流式布局的高度和模式
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//使用wrap_content的流式布局的最终宽度和高度
int width = 0, height = 0;
//记录每一行的宽度和高度
int lineWidth = 0, lineHeight = 0;
//得到内部元素的个数
int count = getChildCount();
mChildPos.clear();
for (int i = 0; i < count; i++) {
//获取对应索引的view
View child = getChildAt(i);
//测量子view的宽和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
//子view占据的宽度
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
//子view占据的高度
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
//换行
if (lineWidth + childWidth > widthSize - getPaddingLeft() - getPaddingRight()) {
//取最大的行宽为流式布局宽度
width = Math.max(width, lineWidth);
//叠加行高得到流式布局高度
height += lineHeight;
//重置行宽度为第一个View的宽度
lineWidth = childWidth;
//重置行高度为第一个View的高度
lineHeight = childHeight;
//记录位置
mChildPos.add(new ChildPos(
getPaddingLeft() + lp.leftMargin,
getPaddingTop() + height + lp.topMargin,
getPaddingLeft() + childWidth - lp.rightMargin,
getPaddingTop() + height + childHeight - lp.bottomMargin));
} else { //不换行
//记录位置
mChildPos.add(new ChildPos(
getPaddingLeft() + lineWidth + lp.leftMargin,
getPaddingTop() + height + lp.topMargin,
getPaddingLeft() + lineWidth + childWidth - lp.rightMargin,
getPaddingTop() + height + childHeight - lp.bottomMargin));
//叠加子View宽度得到新行宽度
lineWidth += childWidth;
//取当前行子View最大高度作为行高度
lineHeight = Math.max(lineHeight, childHeight);
}
//最后一个控件
if (i == count - 1) {
width = Math.max(lineWidth, width);
height += lineHeight;
}
}
// 得到最终的宽高
// 宽度:如果是AT_MOST模式,则使用我们计算得到的宽度值,否则遵循测量值
// 高度:只要布局中内容的高度大于测量高度,就使用内容高度(无视测量模式);否则才使用测量高度
int flowLayoutWidth = widthMode == MeasureSpec.AT_MOST ? width + getPaddingLeft() + getPaddingRight() : widthSize;
int flowLayoutHeight = heightMode == MeasureSpec.AT_MOST ? height + getPaddingTop() + getPaddingBottom() : heightSize;
//真实高度
realHeight = height + getPaddingTop() + getPaddingBottom();
//测量高度
measuredHeight = heightSize;
if (heightMode == MeasureSpec.EXACTLY) {
realHeight = Math.max(measuredHeight, realHeight);
}
// 设置最终的宽高
setMeasuredDimension(flowLayoutWidth, flowLayoutHeight);
}
在测量的过程中就可以获取到每一个子控件的位置,直接缓存,在onLayout中可以直接遍历摆放。
private class ChildPos {
int left, top, right, bottom;
public ChildPos(int left, int top, int right, int bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
}
1.2.摆放onLayout
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
ChildPos pos = mChildPos.get(i);
//设置View的左边、上边、右边底边位置
child.layout(pos.left, pos.top, pos.right, pos.bottom);
}
}
注意:
需要重写generateLayoutParams 返回MarginLayoutParams才可以在onMeasure中获取到控件的Margin值
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
Android自定义ViewGroup-入门的更多相关文章
- android自定义viewgroup之我也玩瀑布流
先看效果图吧, 继上一篇<android自定义viewgroup实现等分格子布局>中实现的布局效果,这里稍微有些区别,每个格子的高度不规则,就是传说的瀑布流布局,一般实现这种效果,要么用第 ...
- Android自定义ViewGroup
视图分类就两类,View和ViewGroup.ViewGroup是View的子类,ViewGroup可以包含所有的View(包括ViewGroup),View只能自我描绘,不能包含其他View. 然而 ...
- Android自定义ViewGroup,实现自动换行
学习<Android开发艺术探索>中自定义ViewGroup章节 自定义ViewGroup总结的知识点 一.自定义ViewGroup中,onMeasure理解 onMeasure(int ...
- android自定义viewgroup实现等分格子布局
先上效果图: 实现这样的效果: 一般的思路就是,直接写布局文件,用LinearLayout 嵌套多层子LinearLayout,然后根据权重layout_weight可以达到上面的效果 还有就是利用g ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu
示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动, ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]
http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...
- Android自定义ViewGroup(四、打造自己的布局容器)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51500304 本文出自:[openXu的博客] 目录: 简单实现水平排列效果 自定义Layo ...
- android自定义viewgroup初步之一----抽屉菜单
转载请注明出处 http://blog.csdn.net/wingichoy/article/details/47832151 几天前在慕课网上看到鸿洋老师的 自定义卫星菜单,感觉很有意思,于是看完视 ...
- Android 自定义ViewGroup手把手教你实现ArcMenu
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37567907 逛eoe发现这样的UI效果,感觉很不错,后来知道github上有这 ...
- Android -- 自定义ViewGroup实现FlowLayout效果
1,在开发的时候,常在我们的需求中会有这种效果,添加一个商品的一些热门标签,效果图如下: 2,从上面效果可以看得出来,这是一个自定义的ViewGroup,然后实现换行效果,让我们一起来实现一下 自定义 ...
随机推荐
- Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal 题解(思维+逆序对)
题目链接 题目大意 给你一个长度为n的字符串,可以交换相邻两个元素,使得这个字符串翻转,求最少多少种次数改变 题目思路 如果要求数组排序所需要的冒泡次数,那其实就是逆序对 这个也差不多,但是如果是相同 ...
- get、post、
1.get请求 get请求会把参数放在url后面,中间用?隔开,也可以把参数放在请求body中,如果参数中有中文,http传的时候requests框架会将中文换成urlencode编码 2.get和p ...
- mysql undo+redo+binlog
rt 数据库事务开始之前,会将要修改的记录存放到UNdo日志里,当事务回滚时或数据库崩溃时,可以利用undo日志撤销未提交事务对数据库产生的影响. 逻辑日志,记录一个过程,提交后不会删除.delete ...
- 莫比乌斯反演进阶-洛谷P2257/HDU5663
学了莫比乌斯反演之后对初阶问题没有任何问题了,除法分块也码到飞起,但是稍微变形我就跪了.用瞪眼观察法观察别人题解观察到主要内容除了柿子变形之外,主要就是对于miu函数的操作求前缀和.进而了解miu函数 ...
- PyQt(Python+Qt)学习随笔:QTreeView树形视图的animated属性
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTreeView树形视图的animated属性用于控制视图在展开或收缩分支时是否展示动画,如果对应 ...
- 爬虫模块-requests
title: python爬虫01 date: 2020-03-08 22:56:12 tags: 1.requests模块 requests模块的底层是urllib,但是比urllib更强大也更加简 ...
- 中间件面试专题:RabbitMQ高频面试问题
- P1654 OSU! 题解
\(x\) 为该位置有 \(1\) 的期望. 统计两个值 : \(suma\) 和 \(sumb\). \(suma\) 表示连续 \(X\) 个 \(1\) , \(X\) 的平方的期望, \(su ...
- 题解-[ZJOI2005]沼泽鳄鱼
题解-[ZJOI2005]沼泽鳄鱼 前置知识: 邻接矩阵 矩阵乘法 矩阵快速幂 [ZJOI2005]沼泽鳄鱼 给一个有 \(N\) 个点,\(M\) 条双向边的图 \(G\),其中有 \(NFish\ ...
- C++ 虚函数表与多态 —— 虚函数表的内存布局
C++面试经常会被问的问题就是多态原理.如果对C++面向对象本质理解不是特别好,问到这里就会崩. 下面从基本到原理,详细说说多态的实现:虚函数 & 虚函数表. 1. 多态的本质: 形 ...