onMeasure方法在控件的父元素正要放置它的子控件时调用。它会问一个问题,“你想要用多大地方啊?”,然后传入两个参数—— widthMeasureSpec和heightMeasureSpec。它们指明控件可获得的空间以及关于这个空间描述的元数据。比返回一个结果要好的 方法是你传递View的高度和宽度到setMeasuredDimension方法里。
接下来的代码片段给出了如何重写onMeasure。注意,调用的本地空方法是来计算高度和宽度的。它们会译解widthHeightSpec和heightMeasureSpec值,并计算出合适的高度和宽度值。
Java代码:
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
intmeasuredHeight=measureHeight(heightMeasureSpec);
intmeasuredWidth=measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight,measuredWidth);
}
privateintmeasureHeight(intmeasureSpec){
//高度测量窗口的回归.
}
privateintmeasureWidth(intmeasureSpec){
//还测量窗口的宽度.
}
边界参数——widthMeasureSpec和heightMeasureSpec,效率的原因以整数的方式传入。在它们使用之前,首先要做的是使用MeasureSpec类的静态方法getMode和getSize来译解,如下面的片段代码所示:
Java代码:
intspecMode=MeasureSpec.getMode(measureSpec);
intspecSize=MeasureSpec.getSize(measureSpec);
接下来的框架代码给出了处理View测量的典型实现:
Java代码:
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
intmeasuredHeight=measureHeight(heightMeasureSpec);
intmeasuredWidth=measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight,measuredWidth);
}
privateintmeasureHeight(intmeasureSpec){
intspecMode=MeasureSpec.getMode(measureSpec);
intspecSize=MeasureSpec.getSize(measureSpec);
//如果没有限制默认大小是指定的.
intresult=500;
if(specMode==MeasureSpec.AT_MOST)
{
//你理想的大小的计算
//在这个最大值控制.
//如果你能控制的充满可用
//外太空返回束缚.
result=specSize;
}
elseif(specMode==MeasureSpec.EXACTLY)
{
//如果你的控制能符合这些界限返回那个价值.
result=specSize;
}
returnresult;
}
privateintmeasureWidth(intmeasureSpec){
intspecMode=MeasureSpec.getMode(measureSpec);
intspecSize=MeasureSpec.getSize(measureSpec);
//如果没有限制默认大小是指定的.
intresult=500;
if(specMode==MeasureSpec.AT_MOST)
{
//理想尺寸的计算你的控制
//在这个最大的尺寸。
//如果你的控制填充的可用空间
//返回外面的束缚。
result=specSize;
}
elseif(specMode==MeasureSpec.EXACTLY)
{
//如果你的控制能符合这些界限返回那个价值.
result=specSize;
}
returnresult;
}
的要求。一个MeasureSpec包含一个尺寸和模式。
有三种可能的模式:
UNSPECIFIED:父布局没有给子布局任何限制,子布局可以任意大小。
EXACTLY:父布局决定子布局的确切大小。不论子布局多大,它都必须限制在这个界限里。
AT_MOST:子布局可以根据自己的大小选择任意大小。
为了减少内存分配,MeasueSpecs用整数表示。这个类提供打包和解包<size,mode>元组为整型。参考方法:public static int makeMeasureSpec(int size,int mode)。
转:http://blog.csdn.net/zjl5211314/article/details/6952698
一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。一个MeasureSpec由大小和模式组成。它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;AT_MOST(至多),子元素至多达到指定大小的值。
它常用的三个函数:
1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)
这个类的使用呢,通常在view组件的onMeasure方法里面调用但也有少数例外,看看几个例子:
a.首先一个我们常用到的一个有用的函数,View.resolveSize(int size,int measureSpec)
8421 public static int resolveSize(int size, int measureSpec) {
8422 int result = size;
8423 int specMode = MeasureSpec.getMode(measureSpec);
8424 int specSize = MeasureSpec.getSize(measureSpec);
8425 switch (specMode) {
8426 case MeasureSpec.UNSPECIFIED:
8427 result = size;
8428 break;
8429 case MeasureSpec.AT_MOST:
8430 result = Math.min(size, specSize);
8431 break;
8432 case MeasureSpec.EXACTLY:
8433 result = specSize;
8434 break;
8435 }
8436 return result;
8437 }
上面既然要用到measureSpec值,那自然表示这个函数通常是在onMeasure方法里面调用的。简单说一下,这个方法的主要作用就是根据你提供的大小和模式,返回你想要的大小值,这个里面根据传入模式的不同来做相应的处理。
再看看MeasureSpec.makeMeasureSpec方法,实际上这个方法很简单:
9023 public static int makeMeasureSpec(int size, int mode) {
9024 return size + mode;
9025 }
这样大家不难理解size跟measureSpec区别了。看看它的使用吧,ListView.measureItem(View child)
2464 private void measureItem(View child) {
2465 ViewGroup.LayoutParams p = child.getLayoutParams();
2466 if (p == null) {
2467 p = new ViewGroup.LayoutParams(
2468 ViewGroup.LayoutParams.MATCH_PARENT,
2469 ViewGroup.LayoutParams.WRAP_CONTENT);
2470 }
2471
2472 int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
2473 mListPadding.left + mListPadding.right, p.width);
2474 int lpHeight = p.height;
2475 int childHeightSpec;
2476 if (lpHeight > 0) {
2477 childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
2478 } else {
2479 childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
2480 }
2481 child.measure(childWidthSpec, childHeightSpec);
2482 }
measureSpec方法通常在ViewGroup中用到,它可以根据模式(MeasureSpec里面的三个)可以调节子元素的大小。
注意,使用EXACTLY和AT_MOST通常是一样的效果,如果你要区别他们,那么你就要使用上面的函数View.resolveSize(int size,int measureSpec)返回一个size值,然后使用你的view调用setMeasuredDimension(int,int)函数。
8406 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
8407 mMeasuredWidth = measuredWidth;
8408 mMeasuredHeight = measuredHeight;
8409
8410 mPrivateFlags |= MEASURED_DIMENSION_SET;
8411 }
然后你调用view.getMeasuredWidth,view.getMeasuredHeigth 返回的就是上面函数里的mMeasuredWidth,mMeasuredHeight的值。
mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。
MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件
大小已经确定的情况,都是精确尺寸。
MeasureSpec.AT_MOST 是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸
只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。
分享到:
相关推荐
我们可以通过继承已有的Android控件,然后覆盖(override)其关键方法,如onDraw()用于绘制控件外观,onTouchEvent()处理触摸事件,onMeasure()和onLayout()则用于布局和尺寸计算。通过这种方法,我们可以改变控件的...
6. **测量和布局**:`onMeasure()`方法用于计算控件的尺寸,遵循MeasureSpec规则。`onLayout()`方法则确定子视图的位置,如果是`ViewGroup`子类,还需要处理子控件的布局。 7. **动画和过渡效果**:可以通过`...
1. 测量(measure):使用MeasureSpec计算控件的大小。 2. 布局(layout):确定控件的位置。 3. 绘制(draw):调用onDraw()方法,使用Canvas进行实际的绘图操作。 四、动画与触摸事件处理 1. 动画:通过...
7. **适配不同设备和Android版本**: 考虑到Android的碎片化问题,自定义的日历控件需要兼容不同的屏幕尺寸、分辨率和Android版本,可能需要使用Support Library或AndroidX库来保证兼容性。 8. **无障碍功能**: 为了...
在Android开发中,自定义控件是提升应用用户体验和界面美观度的重要手段。"android之自定义开关控件"这个主题旨在教你如何在Android平台上创建一个类似苹果iOS Toggle的自定义开关组件。以下是对这个主题的详细讲解...
5. **样式定制**:为了提供良好的用户体验,可能需要对控件的样式进行定制,包括颜色、字体、尺寸等,这可以通过修改控件属性或者使用自定义主题来实现。 6. **封装与复用**:将这个自定义的日期区间选择组件封装...
在Android开发中,自定义控件是提升应用用户体验和界面独特性的重要手段。自定义控件允许开发者根据项目需求创建独特的视图元素,这不仅能够满足个性化设计的需求,还可以优化功能实现,使得代码更加模块化。本篇...
在Android应用开发中,日历控件是一种常用的组件,它允许用户方便地选择日期,常用于事件安排、约会提醒等功能。本压缩包提供的是关于如何在Android中实现自定义日历控件的源代码示例。下面将详细介绍如何在Android...
3. 重写onMeasure()方法,确定控件的尺寸。通常基座图片的大小就是控件的大小。 4. 重写onDraw()方法,利用Canvas绘制背景和指针。在绘制过程中,需要根据指针的位置偏移图片,使其看起来像是在移动。 5. 重写...
10. **响应式设计**: 控件可能需要适配不同的屏幕尺寸和方向,因此可能利用到Android的尺寸维度资源和布局权重。 11. **UI测试**: 为了确保控件在不同设备和情况下正常工作,可能编写了JUnit或Espresso测试用例。 ...
9. **测试与调试**:在实际开发中,开发者需要对轮盘控件进行多方面的测试,包括不同屏幕尺寸、方向切换、触摸性能等,确保其在各种情况下都能正常工作。 10. **文档与注释**:良好的源码应该包含清晰的注释和文档...
`onMeasure()`方法在这个过程中起关键作用,子类可以覆盖这个方法,根据需求计算并设置视图的尺寸,最后通过`setMeasuredDimension(width, height)`保存结果。 2. **layout**阶段:设置视图在屏幕中的位置。`...
这个名为"Android-一个Android图片缩放查看控件支持手势"的项目,旨在提供一个自定义的视图控件,它允许用户通过手势进行图片的放大、缩小以及平移操作,提升用户体验。下面我们将深入探讨这个控件的关键知识点和...
在Android开发中,获取控件的宽度和高度是常见的需求,尤其在自定义视图、动画效果或者布局计算中显得尤为重要。本篇文章将详细讲解如何在Android中获取控件的宽高,并提供测试代码,帮助开发者更好地理解这一知识点...
- 控件允许开发者根据需要设置表头行的高度,这有助于适应不同屏幕尺寸和视觉设计。通过调用特定的方法或设置属性,可以调整表头行的大小,以满足界面的统一性和美观性。 4. **数据行高自定义**: - 类似地,数据...
这可能涉及到对屏幕尺寸和控件尺寸的计算。 5. **事件处理与交互** - 设置适配器(Adapter)来绑定数据源,更新指示器的状态。 - 处理点击事件,更新选中状态并执行相应的动画。 6. **优化与性能** - 使用`...
首先,我们要知道Android中的视图布局是由`LayoutParams`来控制的,它包含了视图在父容器中的位置和尺寸信息。当我们移动一个视图时,通常需要更新这个`LayoutParams`对象,并调用`requestLayout()`方法来通知父布局...
在这里,你需要根据父视图的要求和自身内容来计算合适的尺寸,并使用`setMeasuredDimension()`设定。 4. **事件处理**:如果控件需要响应触摸事件或其他输入事件,你需要重写`onTouchEvent()`或`onTouchEvent...
此外,为了适配不同的设备和屏幕尺寸,我们还需要考虑控件的尺寸自适应和性能优化。 综上所述,创建一个如"RollWeekView"这样的自定义日期选择控件涉及到Android自定义视图、动画、触摸事件处理等多个技术点。通过...
在Android应用开发中,自定义视图控件是常见的需求,尤其在构建具有特定功能或设计风格的应用时。本项目“Android带日程安排的自定义日历控件”就是一个典型的例子,它允许用户查看和管理他们的日程,同时通过红点...