一、
注意:从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只是获取它显示到某个界面的实际宽度。