Android开发手机移动程序开发Android进阶之路

VV-安卓布局总汇篇

2018-11-02  本文已影响3人  e4e52c116681

零、前言

一直以来觉得布局也没什么好讲的,特别是自从有了ConstraintLayout,拖拖接接基本上就行了
最近写个播放器,感觉布局并不是我想的这样简单,有的时候拖不出想要的结果,布局代码改不好也挺尴尬
脱出来的控件毕竟是IDE的智商,一个控件属性非常多,可读性不怎样,所以在此总结一下安卓的布局

插播一段感悟:我经常思考工具与使用者间的关系:

用工具会用工具之差异:良庖岁更刀,割也;族庖月更刀,折也,工具的使用方法体现了一位工匠的技艺
《庖丁解牛》是我最喜欢的一篇古文,如何在做任何事上以无厚入有间,恢恢乎其于游刃必有余地矣是我的思考
文中的八字成为我接触新事物的律典:依乎天理,因其固然。通其理,方用之,是匠者匠师的差异
如果你不懂牛的构造原理,拿一把屠刀固然可杀牛取肉,但庖丁:以神遇而不以目视,官知止而神欲行
提刀而立,为之四顾,为之踌躇满志,善刀而藏之的感觉也就与你无缘,而这是一位匠者的自豪。

写一个程序就像打造一件艺术品,制造的过程便是解牛,IDE、API、运行环境就是我手中的剑
普通屠夫遇牛则斩,好肉坏肉在一起切,煮成一大杂烩。庖丁的匠心独运是我追求的境界:
吾生也有涯,而知也无涯,以有涯随无涯 愿君且行且珍惜。

本文测试图标是svg的安卓xml版,通过精心挑选,如下:
本文测试图标.png

一、首先说开发者选项中的两个布局分析利器:

1.布局的边框显示:
布局边界.png
2.布局的过渡绘制分析:
过渡绘制.png
3.从一个布局看看用法:

布局的嵌套可能导致一篇区域被绘制多次,根据绘制的次数多少分为下面几种颜色:
原色 < 蓝色 < 绿色 < 粉色 < 红色 (吐槽:绿色 > 蓝色总觉得挺别扭)

待分析布局.png
layout/activity_over_draw.xml:用5个白色背景的RelativeLayout嵌套
<?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="350dp"
    android:layout_height="350dp"
    android:background="@android:color/white"
    android:gravity="center"
    tools:context=".MainActivity">
    <RelativeLayout
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:background="@android:color/white">
        <RelativeLayout
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"
            android:background="@android:color/white">
            <RelativeLayout
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_centerInParent="true"
                android:background="@android:color/white">
                <RelativeLayout
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_centerInParent="true"
                    android:background="@android:color/white">
                </RelativeLayout>
            </RelativeLayout>
        </RelativeLayout>
    </RelativeLayout>
</RelativeLayout>

4.讲一下布局的族谱:

可见XXXLayout都继承自ViewGroup,最终都是View,所以View、ViewGroup的通用布局属性都可以用
不同的布局有自己独特的布局属性、详见后文

常见布局.png

一、RelativeLayout

从RelativeLayout源码总寻找@attr查看的特有属性
看起来挺多,但通过下面分分类,也就一目了然了

* @attr RelativeLayout_             gravity
* @attr RelativeLayout_             ignoreGravity
* @attr RelativeLayout_Layout_      layout_alignWithParentIfMissing
* @attr RelativeLayout_Layout_      layout_toLeftOf
* @attr RelativeLayout_Layout_      layout_toRightOf
* @attr RelativeLayout_Layout_      layout_above
* @attr RelativeLayout_Layout_      layout_below
* @attr RelativeLayout_Layout_      layout_alignBaseline
* @attr RelativeLayout_Layout_      layout_alignLeft
* @attr RelativeLayout_Layout_      layout_alignTop
* @attr RelativeLayout_Layout_      layout_alignRight
* @attr RelativeLayout_Layout_      layout_alignBottom
* @attr RelativeLayout_Layout_      layout_alignParentLeft
* @attr RelativeLayout_Layout_      layout_alignParentTop
* @attr RelativeLayout_Layout_      layout_alignParentRight
* @attr RelativeLayout_Layout_      layout_alignParentBottom
* @attr RelativeLayout_Layout_      layout_centerInParent
* @attr RelativeLayout_Layout_      layout_centerHorizontal
* @attr RelativeLayout_Layout_      layout_centerVertical
* @attr RelativeLayout_Layout_      layout_toStartOf
* @attr RelativeLayout_Layout_      layout_toEndOf
* @attr RelativeLayout_Layout_      layout_alignStart
* @attr RelativeLayout_Layout_      layout_alignEnd
* @attr RelativeLayout_Layout_      layout_alignParentStart
* @attr RelativeLayout_Layout_      layout_alignParentEnd

1.gravity

决定内部控件摆放的位置(父控件主动)

gravity.png
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:background="@android:color/white"
    android:gravity="center_horizontal"
    tools:context=".MainActivity">
    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/icon_center"/>
</RelativeLayout>

2.子控件主动找Parent(子循父)
//与父控件左、上、右、下对齐
layout_alignParentLeft  、layout_alignParentTop 、layout_alignParentRight   、layout_alignParentBottom

//居中、水平居中、垂直居中
layout_centerInParent   、layout_centerHorizontal   、layout_centerVertical

//效果等同于-layout_alignParentLeft、layout_alignParentRight,AndroidStudio推荐使用这两个
layout_alignParentStart 、layout_alignParentEnd
RelativeLayout子循父属性一览.png
3.子控件主动找子控件(子循兄)
//参照属性
layout_above、layout_below
layout_toLeftOf、layout_toRightOf   ==   layout_toStartOf、layout_toEndOf
//对齐属性
layout_alignTop、layout_alignBottom、layout_alignBaseline
layout_alignLeft、layout_alignRight ==   layout_alignStart、layout_alignEnd
RelativeLayout子循兄属性一览.png
4.通过一个图总结一下RelativeLayout

布局文件见文后源码,有点长,不贴了
这里说一下:padding和margin,两者都可以让自己与旁边的控件产生间隙,区别在于:
比如你在一个大箱子里,又被箱子里的石头紧紧困住,padding就像缩小自己寻求空隙,margin就是把石头推开
当margin太大,石头不能往外偏移了,石头就会如图四

边距.png

二、ConstraintLayout 约束布局

大学时学solidworks(3D软件)时便对约束有很深的印象,约束可以实现复杂结构的关联

1.定位属性

AndroidStudio中快速打入

ste ==  layout_constraintStart_toEndOf
ss  ==  layout_constraintStart_toStartOf
es  ==  layout_constraintEnd_toStartOf
ete ==  layout_constraintEnd_toEndOf
ttt ==  layout_constraintTop_toTopOf
ttb ==  layout_constraintTop_toBottomOf
btt ==  layout_constraintBottom_toTopOf
btb ==  layout_constraintBottom_toBottomOf
ConstraintLayout定位属性一览.png ConstraintLayout样例.png
2.边距属性
待定位边距属性一览.png
3.乖离率---bias:

layout_constraintHorizontal_bias
layout_constraintVertical_bias

头接父头,尾接父尾,长宽固定的情况不能实现:
实验一下,结果居中了,调节layout_constraintHorizontal_bias的值(0~1)

Horizontal_bias.png
<ImageView
    android:id="@+id/id_iv_center"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@drawable/icon_center"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias=".9"
    app:layout_constraintStart_toStartOf="parent"/>

4.比例宽高:layout_constraintDimensionRatio
<ImageView
    android:id="@+id/id_iv_center"
    android:layout_width="50dp"
    android:layout_height="0dp"
    android:src="@drawable/icon_center"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="1:4"
    android:background="@color/colorPrimary"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"/>
比例宽高.png
5.控件链

还记得是结构的双链表吧,除首位节点,其他都持有前后的引用,这里约束也相似
也能实现一个接着一个,后面有连到前面的结构。

链模式:加在链头,加在链头,加在链头(重要的话说三遍)
水平链模式:layout_constraintHorizontal_chainStyle
垂直链模式:layout_constraintVertical_chainStyle

链.png
<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="230dp"
    android:layout_height="230dp"
    android:background="@android:color/white">
    <!--左-->
    <ImageView
        android:id="@+id/id_iv_left"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/icon_left"
        app:layout_constraintHorizontal_bias=".3"
        app:layout_constraintEnd_toStartOf="@id/id_iv_right"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteY="0dp"/>
    <!--右-->
    <ImageView
        android:id="@+id/id_iv_right"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/icon_right"
        app:layout_constraintEnd_toStartOf="@+id/id_iv_top"
        app:layout_constraintStart_toEndOf="@id/id_iv_left"/>
    <!--上-->
    <ImageView
        android:id="@+id/id_iv_top"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/icon_top"
        app:layout_constraintEnd_toStartOf="@id/id_iv_bottom"
        app:layout_constraintStart_toEndOf="@id/id_iv_right"/>
    <!--下-->
    <ImageView
        android:id="@+id/id_iv_bottom"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/icon_bottom"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/id_iv_top"/>
</android.support.constraint.ConstraintLayout>

注:链自己写比较麻烦,可以在预览区选中,自动生成:

自动生成链.png
6.三个不可视的辅助标签
1).参考线辅助定位:Guideline

就当是一个gone的view,但保留自己的位置信息,为布局提供参考

<android.support.constraint.Guideline
    android:id="@+id/center_in_h"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5"/>
Guideline.png
2).组:Group

试了一下,并不像我想象中的那么强大,不能靠分组定位。可在代码里同组Gone掉,有点鸡肋。

<android.support.constraint.Group
    android:id="@+id/id_left_right"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:constraint_referenced_ids="id_iv_left,id_iv_right"/>
3).屏障:Barrier

这个挺不错的,将view打包,提供一个约束参考,有点像分组定位,可惜貌似只能一边。可看作一个透明的墙,能提供依靠。

barrier.png
<!--左-->
<ImageView
    android:id="@+id/id_iv_left"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:src="@drawable/icon_left"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>
<!--右-->
<ImageView
    android:id="@+id/id_iv_right"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:src="@drawable/icon_right"
    app:layout_constraintStart_toEndOf="@id/id_iv_left"
    app:layout_constraintTop_toTopOf="parent"/>
    
<ImageView
    android:id="@+id/id_iv_center"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:src="@drawable/icon_center"
    app:layout_constraintTop_toBottomOf="@id/barrier"/>
    
<android.support.constraint.Barrier
    android:id="@+id/barrier"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:constraint_referenced_ids="id_iv_left,id_iv_right"
    app:barrierDirection="bottom"/>

三、最后举一个小栗子

可以看出ConstraintLayout可以减少布局的层次,减少过渡绘制的次数
一个0.65的竖直参考线,三个图标形成链,顶底对齐父控件

比较.png
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="70dp"
    android:layout_marginTop="100dp"
    android:foreground="?android:attr/selectableItemBackground"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/id_iv_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:src="@mipmap/icon_default"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/id_tv_music_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="勇气"
        android:textColor="#363636"
        android:textSize="18dp"
        app:layout_constraintBottom_toTopOf="@id/id_tv_singer"
        app:layout_constraintStart_toEndOf="@id/id_iv_icon"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/id_tv_singer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="5dp"
        android:text="葛强丽"
        android:textColor="#898989"
        android:textSize="12dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="@id/id_tv_music_name"
        app:layout_constraintTop_toBottomOf="@id/id_tv_music_name"/>

    <ImageView
        android:id="@+id/id_iv_ctrl"
        android:layout_width="28sp"
        android:layout_height="28sp"
        android:layout_toStartOf="@id/id_iv_next"
        android:src="@drawable/icon_stop_2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/id_iv_next"
        app:layout_constraintStart_toStartOf="@+id/point7_h"
        app:layout_constraintTop_toTopOf="parent"/>

    <ImageView
        android:id="@+id/id_iv_next"
        android:layout_width="28sp"
        android:layout_height="28sp"
        android:layout_toStartOf="@id/id_iv_pre_list"
        android:src="@drawable/icon_next"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/id_iv_pre_list"
        app:layout_constraintStart_toEndOf="@+id/id_iv_ctrl"
        app:layout_constraintTop_toTopOf="parent"/>

    <android.support.constraint.Guideline
        android:id="@+id/point7_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.65"/>

    <ImageView
        android:id="@+id/id_iv_pre_list"
        android:layout_width="28sp"
        android:layout_height="28sp"
        android:src="@drawable/icon_music_list"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/id_iv_next"
        app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

后记:捷文规范

1.本文成长记录及勘误表
项目源码 日期 备注
V0.1--无 2018-11-2 VV-安卓布局总汇篇
2.更多关于我
笔名 QQ 微信 爱好
张风捷特烈 1981462002 zdl1994328 语言
我的github 我的简书 我的CSDN 个人网站
3.声明

1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持

上一篇下一篇

猜你喜欢

热点阅读