您的位置:首页 > 移动开发 > Android开发

Android LineaLayout baselineAligned

2016-03-13 00:53 435 查看
首先看一个我遇到的问题,Layout如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
tools:context="demo.cn.com.androidtest.MainActivity">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="Hello World! Hello World!"
/>
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="Hello World!"
/>
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="Hello World!"
/>
</LinearLayout>

</RelativeLayout>


横着平均放三个Button,得到的显示结果如下



第一行由于内容比较多,按钮整体往下偏移了一点,但是Button属性都一样为什么会出现这种情况,我们给上面布局加上android:baselineAligned=false属性看一下效果

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
tools:context="demo.cn.com.androidtest.MainActivity">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:weightSum="3"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="Hello World! Hello World!"
/>
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="Hello World!"
/>
<Button
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="Hello World!"
/>
</LinearLayout>

</RelativeLayout>


效果如下:



效果就是加上android:baselineAligned=false属性后,按钮的布局对齐了,这是我们需要的正常效果。

为什么会出现上述原因,让我们来分析一下android:baselineAligned的作用。

android:baselineAligned:基准对齐线,这个在中文中不常见,但在以字母为书写语言的其他国家非常常见如下图:



上面的那条红色的线就是基线。关于基线,有如下几点

1.首先这个基线主要是对可以显示文字的View,如TextView,Button等控件的

本例使用的是Button

2.这个baseline指的是这个UI控件的baseline--文字距UI控件顶部的偏移量,本例是距离顶部的偏移

3.LinearLayout控件默认有属性android:baselineAligned为true,如果LinearLayout的orientation为horizontal的话,其中的文字默认是文字对齐的,所以我们什么都不写,LinearLayout要求我们的文字的顶部对齐。这个我们查看源码也可得知

/**
* Whether the children of this layout are baseline aligned.  Only applicable
* if {@link #mOrientation} is horizontal.
*/
@ViewDebug.ExportedProperty(category = "layout")
private boolean mBaselineAligned = true;


如注释描述,只有是LinearLayout是水平的时候才生效,这个变量实际使用如下:

void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec)
{
final int baselineAligned = mBaselineAligned;
 ......
if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
// Optimization: don't bother measuring children who are going to use
// leftover space. These views will get measured again down below if
// there is any leftover space.
if (isExactly) {
mTotalLength += lp.leftMargin + lp.rightMargin;
} else {
final int totalLength = mTotalLength;
mTotalLength = Math.max(totalLength, totalLength +
lp.leftMargin + lp.rightMargin);
}

// Baseline alignment requires to measure widgets to obtain the
// baseline offset (in particular for TextViews). The following
// defeats the optimization mentioned above. Allow the child to
// use as much space as it wants because we can shrink things
// later (and re-measure).
if (baselineAligned) {
final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
child.measure(freeSpec, freeSpec);
} else {
skippedMeasure = true;
 }

......
}


LinearLayout是通过遍历孩子来给每一个孩子测量

如上源码实现:

if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0)刚好符合以本例,本里的测量过程会走这个分支

关键代码:

if (baselineAligned) {
final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
child.measure(freeSpec, freeSpec);
} else {
skippedMeasure = true;
}
如果为true,则给其测量,如果为false就线略过,现在我们只需知道在水平方线上baselineAligned为true,测量的时候会特殊照顾就行,具体也不深挖了。

如下图,我们的基线为画出部分:



baselineAligned为true就要求文字对齐,为false的话则没有这个要求.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: