Android LineaLayout baselineAligned

首先看一个我遇到的问题,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的话则没有这个要求.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值