Android纯代码如何实现复杂自定义控件onMeasure()、onLayout()?
Admin 2022-04-12 群英行业资讯
测量: onMeasure(): 测量自己的大小,为正式布局提供建议
布局: onLayout(): 使用layout()函数对所有子控件布局
绘制: onDraw(): 根据布局的位置绘图
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
参数即父类传过来的两个宽高的"建议值",即把当前view的高设置为:heightMeasureSpec ;宽设置为:widthMeasureSpec,这个参数不是简单的整数类型,而是2位整数(模式类型)和30位整数(实际数值) 的组合,其中模式分为三种:
UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;UNSPECIFIED=00000000000000000000000000000000
EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;EXACTLY =01000000000000000000000000000000
AT_MOST(至多),子元素至多达到指定大小的值。 他们对应的二进制值分别是: AT_MOST =10000000000000000000000000000000
最前面两位代表模式,分别对应十进制的0,1,2,获取模式int值 和 获取数值int值的方法:
int measureWidth = MeasureSpec.getSize(widthMeasureSpec); int measureHeight = MeasureSpec.getSize(heightMeasureSpec); int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec); int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);
上面我们知道了 onMeasure(int widthMeasureSpec, int heightMeasureSpec) 方法参数的意义,下面了解参数对应的三个模式分别对应的意义:
每一个模式都对应的xml布局中的一个值
wrap_content --- MeasureSpec.AT_MOST match_parent --- MeasureSpec.EXACTLY 具体值 --- MeasureSpec.UNSPECIFIED
注意:当模式是MeasureSpec.AT_MOST时,即wrap_content时,需要将大小设置一个数值。
首先先了解几个需要用到的方法:
(1)、setMeasuredDimension
这个方法和onMeasure()方法类似。其实这个方法的作用就是 设置当前View的宽高。
(2)、onLayout
这个方法就和方法类似了,不过少了第一个参数boolean changed
这个方法的目的是用于当前ViewGroup中的子控件的布局,再看方法,只要是继承ViewGroup的类都必须要重写该方法,来实现该控件内部子控件的布局情况。我们写一个自定义类继承ViewGroup实现Linearlayout垂直排列的效果看下:
public class XViewGroup extends ViewGroup{ public XViewGroup(Context context) { super(context); } public XViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } public XViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int measureWidth = MeasureSpec.getSize(widthMeasureSpec); int measureHeight = MeasureSpec.getSize(heightMeasureSpec); int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec); int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec); // 计算所有子控件需要用到的宽高 int height = 0; //记录根容器的高度 int width = 0; //记录根容器的宽度 int count = getChildCount(); //记录容器内的子控件个数 for (int i=0;i<count;i ) { //测量子控件 View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); //获得子控件的高度和宽度 int childHeight = child.getMeasuredHeight(); int childWidth = child.getMeasuredWidth(); //得到最大宽度,并且累加高度 height = childHeight; width = Math.max(childWidth, width); } // 设置当前View的宽高 setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? measureWidth: width, (measureHeightMode == MeasureSpec.EXACTLY) ? measureHeight: height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int top = 0; int count = getChildCount(); for (int i=0;i<count;i ) { View child = getChildAt(i); int childHeight = child.getMeasuredHeight(); int childWidth = child.getMeasuredWidth(); //该子控件在父容器的位置 , 高度是之前所有子控件的高度和开始 ,从上往下排列,就实现了类似Linearlayout布局垂直排列的布局 child.layout(0, top, childWidth, top childHeight); //以父容器左上角为原点进行布局 top = childHeight; } } }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
对于很多喜欢打游戏的人来说,一个好的服务器尤为重要,而我的世界海外服务器就是一款非常适合他们的服务器,他可以保证玩家在玩游戏过程中顺畅性,因为好的服务可以保障玩耍的时候不卡顿,也可以让游戏在玩耍过程中带来更多乐趣,我们来看看玩家认可的海外服务器有哪些?整个游戏界面设置如何?
数据库服务器配置需要多大才合适?数据库服务器需要存放大量重要的数据信息,如果出现问题,会导致数据被泄露,后果不堪设想。所以我们在选择数据库服务器的时候,应该非常注意安全方面的问题。那么,怎样选择数据库服务器才比较好呢?
网站托管是可以减少很多不必要的麻烦,企业自己建立管理服务器的话就需要建立机房,机房能否正常运转也会有很多问题,而真正在关注网站服务器托管费用的时候也可以看看具体包括的费用项目有哪些?只要价格合理,现在有很多服务商都是可以做好托管服务,并且在服务的质量上做的很好。
从页面加载缓慢到网站完全崩溃,常见的服务器问题可能会给你的企业带来灾难。当客户无法访问您的服务时,他们会迅速转向最近的竞争对手。研究表明,加载速度慢的页面会损害品牌认知,增加页面废弃率。停机时间非...
服务器托管服务是指将服务器放在指定服务商,通过远程管理数据中心的服务器的行为。使用托管的数据中心来容纳你的企业服务器可以提供很大的成本优势,利用先进的服务商的配置,我们可以得到更高级别的安全、更高的贷款和更低的延迟。要将服务器托管到数据中心,服务器托管找什么服务商重不重要呢?下面我们来分析一下: