Android开发学习笔记——常用布局
Android常用布局
- Android开发学习笔记——常用布局
- LinearLayout——线性布局
- RelativeLayout——相对布局
- FrameLayout——帧布局
- AbsoluteLayout——绝对布局
- TableLayout——表格布局
- ConstraintLayout——约束布局
- 1、相对定位(Relative Positioning)
- 2、边距(margin)
- 3、居中定位和偏移(Center Positioning和bias)
- 4、圆形定位(Circular positioning)
- 5、尺寸约束(Dimensions constraints)
- 6、链(Chains)
- 7、辅助控件(Guidelines、Barrier、Group)
- 总结
Android开发学习笔记——常用布局
目前Android开发过程我们总是需要使用到各种布局来构建界面,其中主要有LinearLayout(线性布局)、RelativeLayout(相对布局)、FrameLayout(帧布局)、AbsoluteLayout(绝对布局)、TableLayout(表格布局)以及官方在16年新出的布局ConstraintLayout(约束布局)等。接下来,我将对这些布局进行一个详细的说明。
LinearLayout——线性布局
LinearLayout是我们在开发过程中最常用的布局之一,从线性布局的字面意义上我们即可理解为这是一个将子控件水平或垂直线性排列的布局。
1、orientation(方向)
对于线性布局而言,首先我们需要在使用前确定其子控件的排列方向。在线性布局中,我们可以选择水平方向(horizontal)和竖直方向(vertical)排列,在xml中,我们可以使用orientation属性来进行设置。默认为水平方向排列。
android:orientation="vertical" //垂直排列
android:orientation="horizontal" //水平排列
2、gravity和layout_gravity(位置)
在LinearLayout中,布局中的子控件默认是从左上角依次进行水平排列或者垂直排列的。此时,如果需要改变子控件的排列位置,我们可以通过LinearLayout中的gravity或者是子控件的layout_gravity来进行修改。
在线性布局中,gravity属性用于指定其布局中子控件的位置。
android:gravity="center"
其常用属性值包括以下几个:
属性 | 含义 |
---|---|
center | 子控件居中 |
center_horizontal | 子控件水平居中 |
center_vertical | 子控件垂直居中 |
start/end | 子控件居开始/结束位置 |
left/right | 子控件居左部/右部位置 |
top/bottom | 子控件居顶部/底部 |
在使用gravity属性时可以使用"|"符号来同时指明两个属性,如:
android:gravity="center_horizongtal | top" //子控件位于底部水平居中
gravity属性可以指定布局中所有子控件的位置,但是如果我们需要特定布局中某个子控件的位置呢?此时,我们就需要使用到子控件中的layout_gravity属性了,该属性可以指定子控件相对于父布局的位置,可以选择的值于gravity完全相同,且也能够同时选择多个值。如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<Button
android:text="button1"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
此时,布局显示如下图所示:
由此可见,layout_gravity在与gravity发生冲突时,是使用layout_gravity效果的。值得注意的是,在LinearLayout为水平布局时,layout_gravity只能设置子控件在竖直方向上的位置,设置如center_horizontal是无效的;同样的,垂直排列时设置竖直方向是无效的。
3、layout_weight(权重)
在LinearLayout中,layout_weight是一个很重要的属性,指定了子控件占父布局剩余屏幕大小的权重,能够很灵活地控制控件的大小,同时也能够更好地进行适配。其子控件实际大小的计算公式如下:
父布局剩余大小=父布局大小-所有控件初始大小
控件权重=控件声明权重/所有控件声明权重之和(若LinearLayout声明weightSum则等于控件声明权重/weightSum)
控件实际大小=控件声明大小+父布局剩余大小*控件权重
谷歌推荐设置控件的初始化大小为0dp,这样根据公式,即可使控件大小完全满足之间的比例,如将两个textview按照1:2划分屏幕。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:text="textview1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="@color/colorAccent"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:background="@color/colorPrimaryDark"
android:text="textview2"
android:textColor="#FFFFFF" />
</LinearLayout>
而如果,在布局中对子控件的大小进行了初始化,那么此时会先减去控件的初始化大小,然后再对子控件的大小根据比例进行分配。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:text="textview1"
android:layout_width="100dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="@color/colorAccent"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:background="@color/colorPrimaryDark"
android:text="textview2"
android:textColor="#FFFFFF" />
</LinearLayout>
由图可见,textview1是比textview2的宽度要大的,根据公式,我们可知,这是因为确定大小时会先为textview1分配100dp,然后再按照1:2的比例进行分配。
当然,也可能并非所有的控件都需要指定layout_weight,此时,会先减去确定大小的控件,然后再确定大小。比如,有一个常见场景为在同一行中,textview1大小确定,textview2填充剩下布局。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:text="textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/colorPrimaryDark"
android:text="textview2"
android:textColor="#FFFFFF" />
</LinearLayout>
RelativeLayout——相对布局
相对布局RelativeLayout也是我们在开发中最常用的布局之一,顾名思义,相对布局就是描述相对父布局或是其他子控件位置来确定控件自身位置的布局。其相对线性布局更加灵活,随意,可以让子控件出现在布局的任意位置。在相对布局中,子控件是默认在左上角重叠排列的。
RelativeLayout中的属性都很好理解,主要分为两类:一类为相对父布局位置属性,属性值为true和false;一类为相对其他子控件位置,属性值为控件id的引用名。
1、相对父布局(属性值为true或false)
属性 | 含义 |
---|---|
layout_centerHrizontal | 水平居中 |
layout_centerVertical | 竖直居中 |
layout_centerInParent | 完全居中 |
layout_alignParentBottom | 贴着父布局底部边缘 |
layout_alignParentTop | 贴着父布局顶部边缘 |
layout_alignParentLeft / layout_alignParentStart | 贴着父布局左部边缘 |
layout_alignParentRight / layout_alignParentEnd | 贴着父布局右部边缘 |
layout_alignWithParentIfMissing | 如果找不到子控件则以父布局为参照 |
2、相对其他子控件(属性值为id)
属性 | 含义 |
---|---|
layout_below | 位于某控件下方 |
layout_above | 位于某控件上方 |
layout_toLeftOf | 位于某控件左方 |
layout_toRightOf | 位于某控件右方 |
layout_alignTop | 与某控件顶部对齐 |
layout_alignLeft | 与某控件左部对齐 |
layout_alignRight | 与某控右部对齐 |
layout_alignBottom | 与某控件底部对齐 |
layout_alignBaseline | 与某控件基准线对齐 |
FrameLayout——帧布局
在帧布局中,所有子元素全部都被放在布局左上方,并后面的子元素会将前面的子元素进行覆盖遮挡。一般用于在布局中动态添加view或者充当Fragment容器等。
帧布局属性:
android:foreground="@drawable/logo" //前景图像
android:foregroundGravity="center" //前景图像位置
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundGravity="bottom|right"
android:foreground="@drawable/ic_launcher_background">
<TextView
android:text="textview1"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#F2FF2F" />
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#F11111" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#99FAFA" />
</FrameLayout>
AbsoluteLayout——绝对布局
绝对布局AbsoluteLayout是通过设置控件的X和Y坐标,来进行控制控件位置的。一般在开发中都不会选择使用该布局,因为由开发人员来手动设定控件的X和Y坐标及其麻烦,而且对于不同屏幕大小、分辨率都会产生差异,无法进行适配。
使用绝对布局时,子控件通过layout_x和layout_y指定坐标
android:layout_x="20dp"
android:layout_y="20dp"
TableLayout——表格布局
表格布局TableLayout也是属于在开发过程中应用较少的布局,其功能基本可以通过LinearLayout和RelativeLayout实现,而且也更加灵活。表格布局使用表格的形式来排列子控件,通过TableRow来确定表格的行数,TableRow中的控件数量即为列数,列宽与行中最宽组件为准,如果直接在TableLayout中添加控件,那么该控件将占满一行。TableLayout可以通过设置属性对表格中不同列进行隐藏、允许收缩、允许拉伸操作。
android:collapseColumns="0,1" //隐藏0、1列(列号从0开始)
android:shrinkColumns="2" //允许第3列收缩
android:stretchColumns="1" //允许第2列拉伸
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:collapseColumns="1"
android:stretchColumns="2">
<Button
android:text="bt1" />
<TableRow>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="c0"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="c1"/>
<Button
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="c2"/>
</TableRow>
</TableLayout>
如图,该布局中总共2行3列,其中第2列被隐藏,第3列被拉伸充满一行。
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shrinkColumns="1">
<Button
android:text="bt1" />
<TableRow>
<Button
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="c0"/>
<Button
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="c1"/>
<Button
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="c2"/>
</TableRow>
</TableLayout>
在该布局中,一行无法完全显示3列,此时第2列被收缩。
ConstraintLayout——约束布局
约束布局ConstraintLayout作为谷歌16年推出的新布局,受到了谷歌的大力推广和支持,并且已经在AndroidStudio中作为默认布局,逐渐开始取代其他布局,具有着可减少布局嵌套层级进而优化渲染性能的优点,并且能够通过可视化的方式来编写界面,提高了编程效率。
当前,ConstraintLayout提供了多种约束方法,包括相对定位、圆角定位等多种约束定位方式。
1、相对定位(Relative Positioning)
相对定位类似于RelativeLayout,但是其更加灵活,是通过指定控件在水平和垂直方向上相对其它视图的约束来确定自身的位置。其属性格式均为layout_constrain[自身位置]_to[其它视图位置]Of,即将控件的某个方向约束到另一个视图的某个方向,两侧将共享相同位置。视图的约束位置如下:
具体属性如下,属性值均为控件id或是parent(父布局)
- layout_constraintLeft_toLeftOf
- layout_constraintLeft_toRightOf
- layout_constraintRight_toLeftOf
- layout_constraintRight_toRightOf
- layout_constraintTop_toTopOf
- layout_constraintTop_toBottomOf
- layout_constraintBottom_toTopOf
- layout_constraintBottom_toBottomOf
- layout_constraintBaseline_toBaselineOf
- layout_constraintStart_toEndOf
- layout_constraintStart_toStartOf
- layout_constraintEnd_toStartOf
- layout_constraintEnd_toEndOf
如果控件B的左侧约束到控件A的右侧,则有:
其中值得注意的是layout_constraintBaseline_toBaselineOf,Baseline指的是控件的基准线,即控件中文字所在基线,当我们需要两个不等高的TextView文字对齐时,即可使用该属性。
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tt"
android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
android:text="tttt"
app:layout_constraintBaseline_toBaselineOf="@+id/textView4"
app:layout_constraintEnd_toStartOf="@+id/textView4"
app:layout_constraintStart_toStartOf="parent"
android:background="#F29111"/>
该段代码显示效果如下:
如上图,可以看到,两个textview中的文字是居中对齐的。
2、边距(margin)
因为默认一个约束会使其两侧共享同一位置,若控件与某个约束之间存在边距则可以使用margin来设置,具体可用属性如下:
- android:layout_marginStart
- android:layout_marginEnd
- android:layout_marginLeft
- android:layout_marginTop
- android:layout_marginRight
- android:layout_marginBottom
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView7"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:layout_marginStart="50dp"
android:layout_marginLeft="50dp"
android:layout_marginBottom="240dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/textView4" />
如上图所示,由于textview7在左侧与底部分别于textview4的左侧、父布局的底部建立了约束,所以在默认情况下,textview7应该位于父布局底部且与textview4左对齐,但是设置了margin后其位置发生了偏移,相对原有约束产生了边距。
与不可见的控件之间存在边距时,可以使用以下属性:
- layout_goneMarginStart
- layout_goneMarginEnd
- layout_goneMarginLeft
- layout_goneMarginTop
- layout_goneMarginRight
- layout_goneMarginBottom
以上属性用法与margin属性相同,但是只有当约束的控件可见性为View.GONE时才会生效产生边距。比如,在上一例子中,如果使用的时goneMargin…则只有在textview4不可见时,textview7才会发生偏移。
注意: 在约束布局中,一旦某个
3、居中定位和偏移(Center Positioning和bias)
当某个控件在水平或是竖直方向的两个约束为两个相反的约束时,此时,两个约束在两个控件大小不同时无法同时实现,控件就会被两边约束拉到居中的位置,如:
app:layout_constraintEnd_toEndOf="parent" //水平居中
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" //竖直居中
app:layout_constraintBottom_toBottomOf="parent"
在这种情况下,控件默认会处于居中状态,但我们也可以通过调节其bias来调整其偏移量,默认状态下bias为0.5,改变该值就会时控件偏向某一侧
app:layout_constraintHorizontal_bias="0.1"//偏左
app:layout_constraintVertical_bias="0.8" //偏下
4、圆形定位(Circular positioning)
圆形定位是通过控件与控件之间的圆心的距离和角度,来设置约束的。如下图所示:
具体使用属性如下:
- layout_constraintCircle
- layout_constraintCircleRadius
- layout_constraintCircleAngle
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button"
app:layout_constraintCircle="@id/textView6"
app:layout_constraintCircleRadius="100dp"
app:layout_constraintCircleAngle="45"/>
如上图,button圆心位于textview的圆形100dp的距离,角度为45度,这样通过textview的位置即可确定button的位置。
5、尺寸约束(Dimensions constraints)
在ConstraintLayout中,控件存在着三种尺寸控制方式,分别为:自动计算控件大小(warp_content)、固定尺寸和0dp(相对于MATCH_CONSTRAINT),在约束布局中是没有布局嵌套的,所有不存在填充父布局,设置为0dp会自动根据约束条件进行填充。
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00BCD4"
android:text="TextView4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tt"
android:layout_width="0dp"
android:layout_height="100dp"
android:background="#F29111"
android:gravity="center"
android:text="tttt"
app:layout_constraintBaseline_toBaselineOf="@+id/textView4"
app:layout_constraintEnd_toStartOf="@+id/textView4"
app:layout_constraintStart_toStartOf="parent" />
上述代码中,填充效果如下:
同时,约束布局中也可以对控件的尺寸的最值进行设置,具体属性如下:
- android:minWidth 设置布局的最小宽度
- android:minHeight 设置布局的最小高度
- android:maxWidth 设置布局的最大宽度
- android:maxHeight 设置布局的最大高度
当控件的高或者宽至少有一个设置为0dp时,还可以通过layout_constraintDimensionRatio属性设置控件宽高比。
<TextView
android:id="@+id/tt"
android:layout_width="0dp"
android:layout_height="100dp"
android:background="#F29111"
android:gravity="center"
app:layout_constraintDimensionRatio="1:1"
android:text="tttt"
app:layout_constraintBaseline_toBaselineOf="@+id/textView4"
app:layout_constraintEnd_toStartOf="@+id/textView4"
app:layout_constraintStart_toStartOf="parent" />
6、链(Chains)
在ConstraintLayout中,如果多个控件通过双向约束连接到一起,那么就可以看作为一条链,如下图:
其中,链的第一个控件为链头,通过设置链头Ad的layout_constraintHorizontal_chainStyle属性来设置链的样式。其属性值有:
- spread—— 元素散布 (默认);
- spread_inside—— 元素散布,但链的两端贴近 parent;
- packed—— 元素贴合在一起。
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button4"
app:layout_constraintHorizontal_chainStyle="spread"
tools:layout_editor_absoluteY="608dp" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toEndOf="@id/button3"
app:layout_constraintEnd_toStartOf="@id/button5"
tools:layout_editor_absoluteY="610dp" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toEndOf="@id/button4"
app:layout_constraintEnd_toEndOf="parent"
tools:layout_editor_absoluteY="610dp" />
当设置链中的元素的width为0dp时,还可设置链中每个元素的layout_constraintHorizontal_weight属性来创建一个权重链。
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button4"
app:layout_constraintHorizontal_weight="1"
tools:layout_editor_absoluteY="608dp" />
<Button
android:id="@+id/button4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toEndOf="@id/button3"
app:layout_constraintEnd_toStartOf="@id/button5"
app:layout_constraintHorizontal_weight="2"
tools:layout_editor_absoluteY="610dp" />
<Button
android:id="@+id/button5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toEndOf="@id/button4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="3"
tools:layout_editor_absoluteY="610dp" />
7、辅助控件(Guidelines、Barrier、Group)
在约束布局中,还提供了一些辅助控件用于辅助构建布局,包括Guidelines、Barrier和Group。
Guidelines
Guideline就是基线的意思,用于在布局中添加一条(水平或垂直)基准线,然后控件可通过基准线设置约束,基准线在上是不显示的。
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" //基准线方向
app:layout_constraintGuide_percent="0.5" //基准线位置/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="120dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/guideline" />
上述代码实现了两个按钮共同居中的功能,效果如下:
Barrier
Barrier就是屏障的意思,该辅助控件可以在多个控件的一侧创建一个“屏障”,然后其他控件即可通过该屏障设立约束。
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toTopOf="@+id/barrier3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top" //位置,还可以为bottom、left等
app:constraint_referenced_ids="tt,textView4" //引用组件id
/>
Group
group即分组,主要用于将一些可见性可能共同变化的组件分为一组,共同管理。
<androidx.constraintlayout.widget.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="bt1,tv1" //引用的控件id
/>
如上述代码,可通过控制组件group的可见性,来一起控制控件bt1和tv1的可见性。
总结
总体而言,在Android开发中各个布局的基本使用还是比较简单的,但是要根据具体的界面来设计布局,灵活使用各个布局还是需要继续多加练习,优秀的布局设计能够为APP的整体性能带来很大的提高。在这些布局中,约束布局ConstraintLayout能够极大程度上地减少布局间的嵌套,但是使用起来相对复杂,自己还远远不够熟练,还需要不断的练习。
本文地址:https://blog.csdn.net/qq_36425800/article/details/107295064