现在的位置: 首页 > 综合 > 正文

学习日志-onMeasure等问题

2018年05月16日 ⁄ 综合 ⁄ 共 2630字 ⁄ 字号 评论关闭

一、

注意:从Android2.2开始,为了更好的使用,fill_parent被改为match_parent。因为当我们把一个子部件设置为fill_parent之后,该部件不是占有同等级部件剩余的空间,而是和同等级部件重叠在一起。相反,使用match_parent则不会出现重叠的现象。

二、

布局参数

XML布局属性layout_something被定义为布局参数,它们被View和ViewGroup所恰当的保留。每ViewGroup的类实现一个嵌套类扩展ViewGroup.LayoutParams的。这个子类包含的属性类型定义为每个子视图的大小和位置,作适当的视图组。正如你可以看到下图中,父视图组定义为每个子视图(包括子视图组)的布局参数。

每个布局的参数其实是父布局的类型,因为它依赖于父布局而存在的:

图片介绍:可视化的视图层次的每个视图的布局参数 请注意,每一个的LayoutParams子类有它自己的语法设定值。每个子元素必须定义相对它父类合适的LayoutParams,尽管它也可以为自己的子类定义不同的LayoutParams。 所有的视图组包括一个宽度和高度(layout_width和layout_height),每个视图需要定义它们。许多的LayoutParams也包括可选的边距和边框。您可以指定宽度和高度精确的值。大部分您将使用这些常量类设置宽度或高度:wrap_content其内容所需的尺寸大小本身。fill_parent(API等级8改名为match_parent,与它的父视图组一样大。在一般情况下,不建议指定一个布局使用绝对单位,如像素的宽度和高度。相反,推荐采用相对测量,如独立的像素密度单位(DP),wrap_content,或fill_parent,因为它有助于确保您的应用程序将在各种设备的屏幕尺寸显示正确。

布局位置

一个View的几何形状是一个矩形。每一个view的位置都可以用一个坐标和两个尺寸所表示,一个坐标指的是相对最左边和相对最顶部的两个点,两个尺寸是指它的高度和宽度。位置和尺寸的单位都是像素。可以调用视图的方法来获得它的位置, getLeft() 返回左侧的或者X的坐标,getTop()返回顶部或者Y的坐标。这两个方法返回的位置都是相对于它的父容器的位置。例如当getLeft()返回20的时候,说明这个view相对于它的父容器的最左边边缘20像素的位置。此外还提供了getRight(),getBottom()方法来满足一些其他的计算,调用getRight()时类似与getLeft()的计算。

三、对于所有的View默认的权重是0,如果你只设置了一个View的权重大于0,那么这个View将占据除去别的View本身占据的空间的的所有剩余空间。因此这里设置EditText的权重为1保持button没有权重值的状态,使EditText能够占据除了按钮之外的所有空间。

四、最重要的一个问题:

getWidth(): View在设定好佈局后整个View的宽度。

 getMeasuredWidth(): 对View上的内容进行测量后得到的View内容佔据的宽度,前提是你必须在父佈局的onLayout()方法或者此View的onDraw()方法裡调 用measure(0,0);(measure 参数的值你可以自己定义),否则你得到的结果和getWidth()得到的结果一样。

在View里面你可以重写onDraw

 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
                widthMeasureSpec != mOldWidthMeasureSpec ||
                heightMeasureSpec != mOldHeightMeasureSpec) {

            // first clears the measured dimension flag
            mPrivateFlags &= ~MEASURED_DIMENSION_SET;

            if (ViewDebug.TRACE_HIERARCHY) {
                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
            }

            // measure ourselves, this should set the measured dimension flag back
            onMeasure(widthMeasureSpec, heightMeasureSpec);

            // flag not set, setMeasuredDimension() was not invoked, we raise
            // an exception to warn the developer
            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
                throw new IllegalStateException("onMeasure() did not set the"
                        + " measured dimension by calling"
                        + " setMeasuredDimension()");
            }

            mPrivateFlags |= LAYOUT_REQUIRED;
        }

        mOldWidthMeasureSpec = widthMeasureSpec;
        mOldHeightMeasureSpec = heightMeasureSpec;
    }

在这里面它进行了计算自己有多大,它的两个参数值就是XML布局传过去的,然后它把onMeasure这个方法暴露出去,你View可以通过调用这个方法来获取它的数据和修改它的数据,

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }

如果父View调用了它的这个方法,可以修改它宽高,然后在最终渲染的时间,表现出来,而getWidth只是获取它显示到某个界面的实际宽度。

抱歉!评论已关闭.