美文网首页Android 精华Android iOS开发知识库Android技术知识
Hacks布局篇-Hack1 使用weight属性实现控件的居中

Hacks布局篇-Hack1 使用weight属性实现控件的居中

作者: diygreen | 来源:发表于2016-05-06 17:15 被阅读335次

    作者:李旺成

    时间:2016年5月6日


    想要的效果

    想要的效果

    如上图所示,要实现这样一个效果:按钮居中显示,并且占据父控件宽度的一半。

    看上去好像挺简单的,可以有很多实现方案,那最佳方案或者说最简单的方案是不是大家都会呢?

    这里给出两个方案,具体选哪个看自己的实际情况。

    方案一:weightSum 和 layout_weight 配合

    先看效果:

    居中显示宽度为父控件一半(一)

    实现代码

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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:gravity="center"
        android:weightSum="2"
        tools:context="com.diygreen.androidhackslayout.Hack1Activity">
        <Button
            android:id="@+id/btn_center"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="居中按钮" />
    </LinearLayout>
    

    原理分析

    这里涉及到 LinearLayout 的 weightSum 属性与子控件的 layout_weight 属性配合使用。考虑到大家对 layout_weight 应该更了解,这里先讨论下 layout_weight。

    layout_weight 属性

    首先,看一下 layout_weight 属性的作用:
    它是用来分配剩余空间的一个属性,可以设置它的权重

    然后,理解 layout_weight 的“真实含义”
    这个属性大家一般都用过,但是可能都不是很清楚具体是怎么回事(反正我以前是这样,看着显示效果调,效果出来就万事大吉,没有考虑过为什么),这里稍微介绍下 layout_weight 的“真实含义”。

    android:layout_weight 的真实含义是:一旦 View 设置了该属性(假设有效的情况下),那么该 View 的宽度等于原有宽度(android:layout_width)加上剩余空间的占比!

    设屏幕宽度为 L,在两个 View 的宽度都为 match_parent 的情况下,原有宽度为 L,两个的 View 的宽度都为 L,那么剩余宽度为 L-(L+L) = -L, 左边的 View 占比三分之一,所以总宽度是 L+(-L)*1/3 = (2/3)L。事实上默认的 View 的 weight 这个值为0,一旦设置了这个值,那么所在 View 在绘制的时候执行 onMeasure 两次的原因就在这。
    Google 官方推荐,当使用 weight 属性时,将 width 设为 0dp 即可,效果跟设成 wrap_content 是一样的。这样 weight 就可以理解为占比了!(参考:android:layout_weight的真实含义

    最后,稍微总结一下
    在 layout_width 设置为 much_parent 的時候,layout_weight 所代表的是你的控件要优先尽可能的大,但这个大是有限度的,即 much_parent;
    在 layout_width 设置为 wrap_content 的时候(这和设置为 0dp 一致),layout_weight 所代表的是你的控件要优先尽可能的小,但这个小是有限度的,即 wrap_content。(参考自:Android中 android:layout_weight 属性 完美解释

    weightSum 属性

    LinearLayout 的 weightSum 属性,我基本上是第一次使用(就是在这个示例中),老规矩先看看官方的介绍:

    weightSum 属性

    简单解释一下:
    “定义 weight 总和的最大值。如果未指定该值,以所有子控件的 layout_weight 属性的累加值作为总和的最大值。一个典型的案例是:通过指定子控件的 layout_weight 属性为 0.5,并设置 LinearLayout 的 weightSum 属性为 1.0,实现子控件占据可用宽度的 50%”。(参考自:《50 Android Hacks》)

    源码分析

    源码分析

    在上面的代码中, LinearLayout 的 android:weightSum 属性值设置为 "2",表示其内部所有子控件的 weight 比例总和是 2。示例中 LinearLayout 中只有一个子控件:Button。该 Button 的 android:layout_width 设置为 "0dp",因此需要根据 android:weightSum 来决定 Button 的 width。Button 的 android:layout_weight 设置为 "1",即 android:weightSum 属性值的一半,所以,Button 将占据 50% 的可用空间。

    方案二:PercentXxxLayout

    先看效果:

    居中显示宽度为父控件一半(二)

    实现代码

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.percent.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.diygreen.androidhackslayout.Hack1Activity">
        <Button
            android:id="@+id/btn_center"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            app:layout_widthPercent="50%"
            android:text="居中按钮(二)" />
    </android.support.percent.PercentFrameLayout>
    

    原理分析

    百分比布局,做过前端的同学应该知道网页提供百分比计算大小,Web 中支持子控件的宽度可参考父控件的宽度以百分比设置,最外层控件的宽度参考屏幕尺寸以百分比设置。看过一些开源库使用类似的思路,来解决 Andoid 多机型适配的问题。但是,这些方案一般都有些缺点:会增加很多无用的数据,导致apk包变大,等等。

    值得高兴的是,Google 提供了一个叫做 percent 的 Support 库,示例见这里 android-percent-support-lib-sample,上面的示例用的就是 percent 布局中的 PercentFrameLayout。

    有了百分比布局那要实现上述效果就很简单了,关于代码没有什么好讲解的了,下面简单介绍下 percent 库。

    percent Support 库简介

    percent 库提供了两个布局:
    PercentRelativeLayout、PercentFrameLayout,通过名字就可以看出,它们应该是从 FrameLayout 和 RelativeLayout 扩展而来的:

    PercentFrameLayout 继承结构 PercentRelativeLayout 继承结构

    果然如此,FrameLayout 和 RelativeLayout 大家应该都很熟悉了,那了解下 PercentXxxLayout 提供的特有属性应该就可以用起来了。

    PercentXxxLayout 特有属性:

    • layout_widthPercent、layout_heightPercent
    • layout_marginPercent
      layout_marginLeftPercent
      layout_marginTopPercent
      layout_marginRightPercent
      layout_marginBottomPercent
      layout_marginStartPercent
      layout_marginEndPercent

    上面这些属性不用解释了吧!只是加了个 “Percent”,赋值的时候用 xx% 即可, 直接当作 FrameLayout、RelativeLayout 用就可以了。

    简单使用

    这里就不展开讲解了,感兴趣的,或者对该这两个布局不熟悉的可以参考:Android 百分比布局库(percent-support-lib) 解析与扩展

    小结

    weight 属性还是挺有作用的,利用好该属性可以避免使用硬编码的方式带来的副作用,但是它也有局限性 —— 只能在 LinearLayout 中使用。好在,我们现在有了更强大的百分比库了。

    这只是布局技巧的冰山一角,还有很多技巧等待大家发掘,如果你有更好的方案,或者其他布局方面的技巧,希望也可以分享分享。

    项目地址

    AndroidHacks合集
    布局篇
    个人博客
    示例用到代码见:
    Hack1Activity.java
    activity_hack1_1.xml
    activity_hack1_2.xml

    参考

    Android 百分比布局库(percent-support-lib) 解析与扩展
    android:layout_weight的真实含义
    Android中 android:layout_weight 属性 完美解释

    相关文章

      网友评论

        本文标题:Hacks布局篇-Hack1 使用weight属性实现控件的居中

        本文链接:https://www.haomeiwen.com/subject/pvqjrttx.html