1.2 快速掌握 Android 中的六大布局

Android中setGravity的使用 本文介绍了Android中setGravity方法的使用,该方法用于设置视图在父布局中的对齐方式。通过该方法,可以为视图指定在父布局中的位置和对齐方式,从而实现界面布局的灵活控制。通过上述代码,我们成功地使用setGravity方法指定了按钮在布局中的对齐方式。假设我们要创建一个简单的界面,其中包含一个按钮,我们将通过setGravity方法来指定按钮在父布局中的对齐方式。setGravity方法接收一个gravity参数,该参数是一个整数值,用于指定视图在父布局中的对齐方式。 阅读详情

本篇我们介绍了六大布局* Linear Layout(线性布局)、Frame Layout(帧布局)、Relative Layout(相对布局)、Absolute Layout(绝对布局)、Table Layout(表格布局)、Absolute Layout(绝对布局) *的常用属性,然后结合实际开发中遇到的各种场景给出了相应的解决方案和示例用法,并且结合不同布局的各自特点给出了自身特有的属性(重复的属性不会列出),方便大家在后续学习UI排布的课程中进行查阅。最后,给出了 Android 中布局优化的一些建议。

什么是布局?

布局是一种可用于放置很多控件的容器,它可以按照一定的规律调整内部控件的位置,从而编写出精美的界面。当然了,布局的内部除了放置控件外, 也可以放置布局,通过多层布局的嵌套,我们就能够完成一些比较复杂的界面实现。

Layout

为了更好地管理Android应用的用户界面里的个组件,Android提供了布局管理器,通过布局管理器,Android应用的图形用户界面就具有了良好的平台无关性。这就让各个控件都可以有条不紊地摆放在界面上,而不是乱糟糟的。

一、线性布局 Linear Layout

LinearLayout是一种非常常用的布局,正如它名字所描述的一样,这个布局会将它所包含的控件在线性方向上依次排列,当然肯定就不仅只有一个方向,我们可以通过 android:orientation 这个属性指定排列方向是 vertical 还是 horizontal,控件就会在竖直方向上或者水平方向上进行排列。

下面我们通过实例来体会一下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity= "right|center_vertical">
<Button
    android:id="@+id/bn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/bn1"/>
<Button
    android:id="@+id/bn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/bn2"/>
<Button
    android:id="@+id/bn3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/bn3"/>
<Button
    android:id="@+id/bn4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/bn4"/>
<Button
    android:id="@+id/bn5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/bn5"/>
</LinearLayout>

上面的布局界面很简单,只是很简单的定义了一个线性布局,在布局中定义了五个按钮并制定了属性“android:gravity = “right | center_vertical””,实际运行效果如下:
LinearLayout效果一

如果将上面的属性改为“android:gravity = “bottom | center_horizontal””,那么实际运行效果为:
LinearLayout效果二

也就是说在垂直布局的前提下底部居中、水平居中,就变成了这个样子,可以看到属性对局部的影响是很大的。

下面列出LinearLayout常用的属性:

android:layout_gravity: 本元素相对于父元素的重力方向
android:layout_weight:子元素对未占用空间水平或垂直分配权重值
android:gravity[setGravity(int)] :本元素所有子元素的重力方向
android:orientation[setOrientation(int)]:线性布局以列或行来显示内部子元素
android:divider[setDividerDrawable(Drawable)]:设置垂直布局时两个控件之间的分隔条
android:baselineAligned[setBaselineAligned(boolean)]:该属性为false,将会阻止该布局管理器与它的子元素的基线对齐
android:measureWithLargestChild[setMeasureWithLargestChildEnabled(boolean)]当该属性设置为true时,所有带权重的子元素都会具有最大子元素的最小尺寸

问1:android:layout_gravity 和 android:gravity 有什么区别?

  • android:gravity:对元素本身起作用-本身元素显示在什么位置
  • android:layout_gravity:相对与它的父元素-元素显示在父元素的什么位置

* 如:Button控件 *
- android:layout_gravity 表示button在界面上的位置
- android:gravity 表示button上的字在button上的位置

问2:受控子元素如何设置?

LinearLayout的所有子元素都受 LinearLayout.LayoutParams 的控制,因此 Linear Layout 包含的子元素可以额外指定以下属性:

  • android:layout_gravity 子元素在LinearLayout中的对齐方式
  • android:layout_weight 子元素在LinearLayout中所占的权重

所以我们要实现第一个的 1:2 的效果,只需要分别把两个 Linear Layout 的 weight 分别设置成1和2就可以了。

比如将上述布局代码改为如下方式:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:background="#2fc1ff"
        android:layout_weight="1"/>
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:background="#f7242b"
        android:layout_weight="2"/>
</LinearLayout>
那么实际的运行效果为:

权重分配效果

用法归纳:

按比例划分水平方向,将涉及到的 View 的 android:width 属性设置为 0dp,然后设置为 android weight 属性设置比例即可;类推竖直方向,只需设 android:height 为 0dp,然后设 weight 属性即可!


二、相对布局 Relative Layout

RelativeLayout 也是一种非常常用的布局,和 LinearLayout 的排列规则不同的是, RelativeLayout 显得更加随意一些,它总是通过相对定位的方式让控件出现在布局的任何位置,比如说相对容器内兄弟组件、父容器的位置决定了它自身的位置。也正因为如此, RelativeLayout 中的属性非常多,不过这些属性都是有规律可循的。

实现一个梅花布局效果:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    <!-- 定义该组件位于父容器中间 -->
    <TextView
        android:id="@+id/view01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_centerInParent="true"/>
    <!-- 定义该组件位于view01组件的上方 -->
    <TextView
        android:id="@+id/view02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_above="@id/view01"
        android:layout_alignLeft="@id/view01"/>
    <!-- 定义该组件位于view01组件的下方 -->
    <TextView
        android:id="@+id/view03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_below="@id/view01"
        android:layout_alignLeft="@id/view01"/>
    <!-- 定义该组件位于view01组件的左边 -->
    <TextView
        android:id="@+id/view04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_toLeftOf="@id/view01"
        android:layout_alignTop="@id/view01"/>
    <!-- 定义该组件位于view01组件的右边 -->
    <TextView
        android:id="@+id/view05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/leaf"
        android:layout_toRightOf="@id/view01"
        android:layout_alignTop="@id/view01"/>
</RelativeLayout>
运行效果如下:

RelativeLayout 梅花布局效果

代码稍微复杂一点,不过难以理解的也就两个属性,一个是 android:layout_toxxxOf,这个是一个控件位于另一个控件上下左右的相对位置,另一个是android:layout_alignxxx,表示一个控件与另一个控件对齐,这里我们列出更详细的属性规则:

相对位置规则:
android:layout_above 将该控件的底部至于给定ID的控件之上
android:layout_below 将该控件的顶部至于给定ID的控件之下
android:layout_toLeftOf 将该控件的右边缘和给定ID的控件的左边缘对齐
android:layout_toRightOf 将该控件的左边缘和给定ID的控件的右边缘对齐
兄弟控件对齐规则:
android:layout_alignBaseline 将该控件的baseline和给定ID的控件的baseline对齐
android:layout_alignBottom 将该控件的底部边缘与给定ID控件的底部边缘对其
android:layout_alignTop 将给定控件的顶部边缘与给定ID控件的顶部对齐
android:layout_alignLeft 将该控件的左边缘与给定ID控件的左边缘对齐
android:layout_alignRight 将该控件的右边缘与给定ID控件的右边缘对齐
父控件对齐规则:
android:alignParentBottom 如果该值为true,则将该控件的底部和父控件的底部对齐
android:layout_alignParentLeft 如果该值为true,则将该控件的左边与父控件的左边对齐
android:layout_alignParentRight 如果该值为true,则将该控件的右边与父控件的右边对齐
android:layout_alignParentTop 如果该值为true,则将空间的顶部与父控件的顶部对齐
中央位置规则:
android:layout_centerVertical 如果值为真,该控件将被至于垂直方向的中央
android:layout_centerHorizontal 如果值为真,该控件将被至于水平方向的中央
android:layout_centerInParent 如果值为真,该控件将被至于父控件水平方向和垂直方向的中央
重力规则:
android:gravity[setGravity(int)]设置容器内各个子组件的重力方向
android:ignoreGravity[setIgnoreGravity(int)]设置容器哪个子组件的不受重力方向影响


三、帧布局 Frame Layout

Frame Layout 相比于前面两种布局就简单多了,你可能因此就觉得它的应用场景会少很多,不过也要看情况,如果是应用在比较复杂的自定义布局的时候,那么帧布局还是很受欢迎的,因为这种布局没有任何的定位方式,所有的控件都会摆放在布局的左上角,不像其它布局那样充满了各种各样的规则。当你翻开帧布局的源码的时候也会惊奇的发现相比于其它布局它的代码量要少很多,这就导致了在复杂的自定义布局控件中选用帧布局作为父类的话就会一定程度上提升UI的渲染的性能。

实现一个叠加效果:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
    <!-- 依次定义6个TextView,先定义的TextView位于底层,后定义的TextView位于上层 -->
    <TextView
        android:id="@+id/view01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="160pt"
        android:height="160pt"
        android:background="#f00"/>
    <TextView
        android:id="@+id/view02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="140pt"
        android:height="140pt"
        android:background="#0f0"/>
    <TextView
        android:id="@+id/view03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="120pt"
        android:height="120pt"
        android:background="#00f"/>
    <TextView
        android:id="@+id/view04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="100pt"
        android:height="100pt"
        android:background="#ff0"/>
    <TextView
        android:id="@+id/view05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="80pt"
        android:height="80pt"
        android:background="#f0f"/>
    <TextView
        android:id="@+id/view06"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:width="60pt"
        android:height="60pt"
        android:background="#0ff"/>
</FrameLayout>

运行起来的效果是:
FrameLayout 布局效果

帧布局容器为每个加入其中的组件创建一个空白的区域(即一帧),每个子组件占据一帧,这些帧都会根据gracity属性自动对齐并按照添加的顺序先后叠加在一起。

FrameLayout的一些属性:
android:foreground[setForeground(Drawable)] 定义帧布局容器的绘图前景图像
android:foregroundGravity[setForegroundGravity(int)] 定义绘图前景图像的重力属性


四、表格布局 Table Layout

Table Layout 允许我们使用表格的方式来排列控件。既然是表格,那就一定会有行和列,在设计表格时我们尽量应该让每一行都拥有相同的列数,这样的表格也是最简单的。不过有时候事情并非总会顺从我们的心意,当表格的某行一定要有不相等的列数时, 就需要通过合并单元格的方式来应对。

下面的例子示范了如何用 Table Layout 来管理布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>

    <!-- 定义第一个表格布局,指定第2列允许收缩,第3列允许拉伸 -->
    <TableLayout android:id="@+id/TableLayout01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:shrinkColumns="1"
        android:stretchColumns="2">
        <!-- 直接添加按钮,它自己会占一行 -->
        <Button android:id="@+id/ok1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="独自一行的按钮"/>
        <!-- 添加一个表格行 -->
        <TableRow>
            <!-- 为该表格行添加三个按钮 -->
            <Button android:id="@+id/ok2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="普通的一个按钮"/>
            <Button android:id="@+id/ok3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="收缩按钮"/>
            <Button android:id="@+id/ok4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="拉伸按钮"/>
        </TableRow>
    </TableLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>

    <!-- 定义第2个表格布局 ,指定第2列隐藏-->
    <TableLayout android:id="@+id/TableLayout02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:collapseColumns="1">
        <!-- 直接添加按钮,它自己会占一行 -->
        <Button android:id="@+id/ok5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="独自一行的按钮"/>
        <!-- 添加一个表格行 -->
        <TableRow>
            <!-- 为该表格行添加三个按钮 -->
            <Button android:id="@+id/ok6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="普通按钮1"/>
            <Button android:id="@+id/ok7"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="普通按钮2"/>
            <Button android:id="@+id/ok8"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="普通按钮3"/>
        </TableRow>
    </TableLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>

    <!-- 定义第3个表格布局,指定第2列和第3列可以被拉伸-->
    <TableLayout
        android:id="@+id/TableLayout03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stretchColumns="1,2">
        <!-- 直接添加按钮,它自己会占一行 -->
        <Button
            android:id="@+id/ok9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="独自一行的按钮"
            />
        <!--定义一个表格行-->
        <TableRow>
        <!-- 为该表格行添加三个按钮 -->
        <Button
            android:id="@+id/ok10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="普通按钮"
            />
        <Button
            android:id="@+id/ok11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拉伸的按钮"
            />
        <Button
            android:id="@+id/ok12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拉伸的按钮"
            />
        </TableRow>
        <!--定义一个表格行-->
        <TableRow>
            <!-- 为该表格行添加两个按钮 -->
            <Button
                android:id="@+id/ok13"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="普通按钮"
                />
            <Button
                android:id="@+id/ok14"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="拉伸的按钮"
                />
        </TableRow>
    </TableLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#3354fc"/>
</LinearLayout>
上面定义了三个 Table Layout ,通过 TextView 分割开来并通过代码指定了它们对各自列的控制行为:
  • 第一个TableLayout :指定第2列允许收缩,第3列允许拉伸
  • 第二个TableLayout :指定第2列隐藏
  • 第三个TableLayout :指定第2列和第3列可以被拉伸

并且上面的每个按钮宽度所用的属性都是 android:layout_width=”wrap_content” ,正常来讲按钮只要包裹住美容即可,但是因为我们指定了相应列的属性,那么可以看到运行的效果如下:
TableLayout 布局效果

相关的属性:
android:collapseColumns[setColumnCollapsed(int,boolean)] 设置需要被藏的列的列号,多个列号之间用逗号隔开
android:shrinkColumns[setShrinkAllColumns(boolean)] 设置允许被收缩的列的列号,多个列号之间用逗号隔开
android:stretchColumns[setStretchAllColumns(boolean)] 设置允许被拉伸的列的列号,多个列号之间用逗号隔开


五、网格布局 Grid Layout

GridLayout是Android4.0之后新增的布局管理器,因此正常情况下需要在 Android 4.0 之后的版本中才能使用,如果希望在更早的版本中使用的话,需要导入相应的支撑库(v7包的gridlayout包)。

Grid Layout 和前面所讲的 Table Layout(表格布局) 有点类似,不过他有很多前者没有的东西,因此也更加好用:
- 可以自己设置布局中组件的排列方式
- 可以自定义网格布局有多少行、列
- 可以直接设置组件位于某行某列
- 可以设置组件横跨几行或者几列

实现一个计算器界面:

<?xml version="1.0" encoding="utf-8" ?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:rowCount="6"
            android:columnCount="4"
            android:id="@+id/root">
    <!-- 定义一个横跨4列的文本框,并设置该文本框的前景色、背景色等属性  -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:textSize="50sp"
        android:layout_marginLeft="2pt"
        android:layout_marginRight="2pt"
        android:padding="3pt"
        android:layout_gravity="right"
        android:background="#eee"
        android:textColor="#000"
        android:text="0"/>
    <!-- 定义一个横跨4列的按钮 -->
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:text="清除"/>
</GridLayout>

首先在布局文件中定义了一个 6*4 的 Grid Layout,然后在该布局中添加两个组件并且每个组件均横跨4列,接下来在Java中动态添加16个按钮:

public class MainActivity extends Activity
{
    GridLayout gridLayout;
    // 定义16个按钮的文本
    String[] chars = new String[] {
                    "7" , "8" , "9" , "÷",
                    "4" , "5" , "6" , "×",
                    "1" , "2" , "3" , "-",
                    "." , "0" , "=" , "+"
            };
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        gridLayout = (GridLayout) findViewById(R.id.root);
        for(int i = 0 ; i < chars.length ; i++)
        {
            Button bn = new Button(this);
            bn.setText(chars[i]);
            // 设置该按钮的字号大小
            bn.setTextSize(40);
            // 设置按钮四周的空白区域
            bn.setPadding(5 , 35 , 5 , 35);
            // 指定该组件所在的行
            GridLayout.Spec rowSpec = GridLayout.spec(i / 4 + 2);
            // 指定该组件所在的列
            GridLayout.Spec columnSpec = GridLayout.spec(i % 4);
            GridLayout.LayoutParams params = new GridLayout.LayoutParams(
                    rowSpec , columnSpec);
            // 指定该组件占满父容器
            params.setGravity(Gravity.FILL);
            gridLayout.addView(bn , params);
        }
    }
}

Java类中采用循环的方式向 Grid Layout 中添加了16个按钮,指定了每个按钮所在的行号和列号,并指定这些按钮会自动填充单元格的所有空间——避免了单元格中的大量空白,运行效果如下:
Grid Layout 布局效果

以下为GridLayout常用属性:

排列对齐:
- 设置组件的排列方式: android:orientation=”” vertical(竖直,默认)或者horizontal(水平)
- 设置组件的对齐方式: android:layout_gravity=”“[setGravity(int)] center,left,right,buttom,如果想同时用两种的话:buttom|left
设置布局为几行几列:
- 设置有多少行:android:rowCount=”4”[setrowCount(int)] //设置网格布局有4行
- 设置有多少列:android:columnCount=”4”[setColumnCount(int)] //设置网格布局有4列

设置某个组件位于几行几列:
- 组件在第几行:android:layout_row = “1” //设置组件位于第二行
- 组件在第几列:android:layout_column = “2” //设置该组件位于第三列
设置某个组件横跨几行几列:
- 横跨几行:android:layout_rowSpan = “2” //纵向横跨2行
- 横跨几列:android:layout_columnSpan = “3” //横向横跨2列

其他设置:
- 布局管理器采用的对齐方式:android:alignmentMode[setAlignmentMode(int)]
- 布局管理器是否保留列序号:android:columnOrderPreserved[setColumnOrderPreserved(boolean)]
- 布局管理器是否保留行序号:android:rowOrderPreserved[setRowOrderPreserved(boolean)]
- 布局管理器是否使用默认的页边距:android:useDefaultMargins[setUseDefaultMargins(boolean)]


六、绝对布局 Absolute Layout

Absolute Layout 就像它名字所展现的那样,它不提供任何布局控制,而是由开发人员自己通过X、Y坐标来控制组件的位置。所以绝大多数情况下我们是不采用绝对布局这种布局方式的,因为运行Android应用的手机往往千差万别,屏幕大小、分别率、屏幕密度等都可能存在较大的差异,使用绝对布局的话很难做机型适配,因此我们了解这种布局方式即可。

先了解下代码:

<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 定义一个文本框,使用绝对定位 -->
    <TextView
        android:layout_x="20dp"
        android:layout_y="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="用户名:"/>
    <!-- 定义一个文本编辑框,使用绝对定位 -->
    <EditText
        android:layout_x="80dp"
        android:layout_y="15dp"
        android:layout_width="wrap_content"
        android:width="250dp"
        android:layout_height="wrap_content" />
    <!-- 定义一个文本框,使用绝对定位 -->
    <TextView
        android:layout_x="20dp"
        android:layout_y="80dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="密  码:"/>
    <!-- 定义一个文本编辑框,使用绝对定位 -->
    <EditText
        android:layout_x="80dp"
        android:layout_y="75dp"
        android:layout_width="wrap_content"
        android:width="250dp"
        android:layout_height="wrap_content"
        android:password="true"/>
    <!-- 定义一个按钮,使用绝对定位 -->
    <Button
        android:layout_x="130dp"
        android:layout_y="135dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登   录"/>
</AbsoluteLayout>

使用绝对布局需要像上面这样给每个子组件都指定 android:layout_x、android:layout_y 两个定位属性,这样才控制得了每个子组件在容器中出现的位置,运行得到的效果如下:
Absolute Layout 布局效果

实际上想要通过绝对布局达到以上的效果需要反复多次运行比对,很显然这样的编程方式要繁琐的多,而且在不同屏幕上的显示效果差异巨大,这里给出Android中常用的距离单位:

px(像素):每个对应屏幕上的一个点
dip或dp(device independent pixels,设备独立像素):一种基于屏幕密度的抽象单位,在每英寸160点的显示器上,1dip=1px
sp(scaled pixels,比例像素):主要处理字体的大小,可以根据字体大小首选项进行缩放
in(英寸):标准长度单位


Android 中布局的优化常用措施介绍

1、尽可能减少布局的嵌套层级

可以使用 sdk 提供的 hierarchyviewer 工具分析视图树,帮助我们发现没有用到的布局。

2、不用设置不必要的背景,避免过度绘制

比如父控件设置了背景色,子控件完全将父控件给覆盖的情况下,那么父控件就没有必要设置背景。

3、使用标签复用相同的布局代码

4、使用标签减少视图层次结构

该标签主要有两种用法:

1) 因 为 所 有 的 Activity 视 图 的 根 节 点 都 是 Frame Layout , 因 此 如 果 我 们 的 自 定 义 的 布 局 也 是 Fragmen Layout 的时候那么可以使用 merge 替换。
2) 当应用 Include 或者 View Stub 标签从外部导入 xml 结构时,可以将被导入的 xml 用 merge 作为根节点表示,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余的节点。
只能作为 xml 布局的根元素。

5、通过实现 View 的延迟加载

布局如下:
<ViewStub
android:id="@+id/vs"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:inflatedId="@+id/my_view"
android:layout="@layout/my_layout" />
Java核心代码:
public void loadVS(View view){
ViewStub vs = (ViewStub) findViewById(R.id.vs);
View inflate = vs.inflate();
int inflatedId = vs.getInflatedId();
int id = inflate.getId();
Toast.makeText(this, "inflatedId="+inflatedId+"***"+"id="+id,
Toast.LENGTH_SHORT).show();

点击关注,第一时间获得后续文章。

联系方式:

简书:WillFlow
优快云:WillFlow
微信公众号:WillFlow

微信公众号:WillFlow

Android六大布局 阅读详情

相关推荐

【feature_column处理】- indicator_column(指示列)和embedding_column(嵌入列)

1. 开胃菜 我们先来了解一下tf.feature_column.input_layer def input_layer(features, feature_columns, weight_collections=None, trainable=True, cols_to_vars=None, cols_to_output_tensors=None)

DataAlgo 1487

android setGravity()的使用

今天,简单讲讲android LinearLayout中如何使用setGravity()。之前,在做一个功能时,需要根据数据的变化设置LinearLayout的gravity 。之前,自己写代码都是直接在xml文件里通过roid:gravity设置的属性,这次需要在java代码里动态设置时,居然不知道怎么设置。后来,在网上搜索了资料后,发现setGravity()就可以设置,这里记录一下。在进行U...

谢岩的博客 3万+

保姆级教程:在Ubuntu 20.04上从零搞定ROS Noetic和RealSense驱动,为无人机开发铺路

本文提供了一份详细的Ubuntu 20.04环境下ROS Noetic和RealSense驱动安装指南,专为无人机开发环境搭建设计。从系统配置、ROS安装到RealSense驱动集成,涵盖所有关键步骤和常见问题解决方案,帮助开发者快速搭建自主空中机器人开发平台。

weixin_30329623的博客 65

Android Layout的属性

FrameLayout,GridLayout,LinearLayout,RelativeLayout简介。

Dsa_ 2983

运动控制中的编码器信号优化:滤波技术实战解析

本文深入解析运动控制系统中编码器信号的滤波技术优化方案。从硬件RC低通滤波器参数计算到软件卡尔曼滤波算法实践,详细介绍了如何有效抑制传导干扰、辐射干扰和机械振动带来的信号噪声。通过半导体设备升级案例,展示了三级混合滤波架构如何将位置检测精度提升至±0.8μm,为工程师提供了一套完整的信号优化方法论。

weixin_29247219的博客 237

企业AI Agent审计与合规:从日志留存到网络联动的完整落地指南

审计日志是企业安全与合规体系的基石,尤其在AI Agent大规模接入业务后,如何完整记录其行为链成为新的挑战。从日志留存180天到PCI DSS合规要求,审计体系需要覆盖会话、推理、工具调用、数据访问等关键环节,并结合不可篡改的存储设计,确保证据链可信。同时,借鉴上网行为管理设备对应用行为控制审计的思路,以及Kismet被动监测网络流量的方法论,将网络侧审计与应用侧日志交叉验证,能有效发现越权和异常行为。本文从日志采集、全链路追踪、基线预警到多租户隔离,系统梳理了AI Agent审计与合规落地的关键路径,帮

weixin_32234493的博客 264

Android之View类(下)

视图控件TextView和EditView (1)TextView:其是View类的子类,其作用是显示文本,,相当于一个标签。TextView的主要属性如下: android:text:其方法为setText(CharSequence),控件显示的文本。一般放在string.xml文件中,更具有扩展性; android:textColor:其方法为setTextColor(int),设置文本...

qq_42237214的博客 301

UVM自学笔记3——项目之三——从零开始搭建ahb_sramc验证平台

创建如下所示的目录结构: 2.在tb的文件下:顶层的testbench如下:在tb中,第24行的代码将uvm宏相关的内容include进来,第26行的代码把uvm_pkg包导入进来,然后将agent相关的包(ahb_pkg/sram_pkg),testcase相关的包(uvm_ahb_sram_test_pkg)以及env相关的包(uvm_ahb_sram_env_pkg)都导入进来,在第38行和39行将接口以virtual interface的形式配置给ahb_agent和sramc_agent下

ZhangShuHuai11的博客 9476

android梅花形布局,2.1.2 快速掌握 Android 中的六大布局

本篇我们介绍了六大布局Linear Layout(线性布局)、Frame Layout(帧布局)、Relative Layout(相对布局)、Absolute Layout(绝对布局)、Table Layout(表格布局)、Absolute Layout(绝对布局)的常用属性,然后结合实际开发中遇到的各种场景给出了相应的解决方案和示例用法,并且结合不同布局的各自特点给出了自身特有的属性(重复的属性...

weixin_28953819的博客 655

Google Gemini 模型本地可视化

Google近期发布了Gemini模型,而且开放了Gemini Pro API,Gemini Pro 可免费使用!Gemini Pro支持全球180个国家的38种语言,目前接受文本、图片作为输入并生成文本作为输出。Gemini Pro的表现超越了其他同类模型,当前版本配备了 32K 文本上下文窗口,可免费使用,且其定价将十分有竞争力。Gemini Pro具备丰富的功能:函数调用、数据嵌入、语义检索、自定义知识嵌入以及聊天功能。

HJ_blog 1246

LLaMA Factory添加新模型template的实战解析

本文主要介绍了LLaMA Factory添加新模型template的实战解析,希望对使用大语言模型的同学们有所帮助。 文章目录 1. 前言 2. 实战解析 2.1 检查代码 2.2 修改代码

herosunly的博客 19万+

Android六大基本布局

一.基本理论 Android六大基本布局分别是:线性布局LinearLayout、表格布局TableLayout、相对布局RelativeLayout、 层布局FrameLayout、绝对布局AbsoluteLayout、网格布局GridLayout。 其中,表格布局是线性布局的子类。网格布局是android 4.0后新增的布局。 在手机程序设计中,绝对布局基本上不用,用得相对较多的是线性布局和相...

qq_34322008的博客 339

MATLAB - 浮动基座机器人的逆运动学

本例演示如何解决以浮动底座为模型的机器人的逆运动学问题。浮动底座机器人可以在空间中自由平移和旋转,具有六个自由度。浮动基座机器人的逆运动学问题适用于空间应用,即使用安装在浮动和致动基座上的机械臂在空间操纵物体,也适用于躯干和腿部可在空间自由移动的行走机器人。请注意,刚体树对象表示具有固定基体的刚体树。这意味着刚体树的基体在世界中具有固定的位置和方向。您可以在基体上附加一个 “浮动 ”类型的刚体关节,为具有浮动基体的机器人建模,以用于动态模拟等某些应用。

机器人控制与仿真应用 2439

Android(1)——基础与Android六大布局

文章目录Android1 概述 Android 1 概述

weixin_45044097的博客 895

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

六大布局之FrameLayout

前言 上一期我们给大家讲解了LinearLayout,这一期我们为大家讲解一下FrameLayout(帧布局)的使用,相较于其他布局,FrameLayout可以说的上是最简单的一个,并且其使用范围相对来说也相对较小,但是也是Android中的六大布局之一,面试的时候还是会碰到的,所以让我们赶紧...

chuojuguo6918的博客 212

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

android六大布局和UI组件

一:android之六大布局 1、在4.0以前版本中一共有五种布局,都是ViewGroup的子类。分别是AbsoluteLayout、RelativeLayout、LinearLayout、(FrameLayout)、TableLayout。而TableLayout是LinearLayout的子类。(中文分别是:绝对布局、相对布局、线性布局、帧布局、表格布局)。 2、在2.2操作系统中将Ab...

俊墨客 1636

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

由Android官方团队带你学习Android Studio的布局编辑器

/ 今日科技快讯 /小鹏道歉未能换来认可,小鹏汽车车主集体维权要求退车。部分小鹏汽车用户表示,自己于2018年5月订购了小鹏汽车,但是等到今年5月才提到车,新款就...

郭霖 1198

Android基础:常见布局

Android中的UI一般都是由多个Activity组成,视图都是通过一个个组件构成,像Button、TextView、ImageView等,而包裹这些组件的我们称之为布局。 Android中传统的五大布局分别是LinearLayout(线性布局)、RelativeLayout(相对布局)、FrameLayout(帧布局)、AbsoluteLayout(绝对布局)、TableLayout(表格布...

weixin_34252090的博客 141

Android5.1.1特殊功能,居然还能防盗!Android 5.1的六大功能盘点

相信很多手持谷歌Nexus系列设备的用户目前已经接收到了Android 5.1的推送消息,但是对于这个新系统相信很多人还是比较陌生,为此小编特地为大家总结了该版本Android系统的六大改变。1.设备防盗功能Android 5.1的这个新功能目前只有Nexus 6和Nexus 9可以享受,其他Nexus设备则与它无缘。只要开启了设备防盗功能,你的设备一旦丢失就会保持锁定状态,即使他人进行出厂重置都...

weixin_42715608的博客 942

Android布局基础

【代码】Android布局基础。

2201_76124988的博客 621

Android开发——线性布局

做个笔记,摘抄网上内容。 参考文献: a,https://www.runoob.com/w3cnote/android-tutorial-view-viewgroup-intro.html b,https://www.runoob.com/w3cnote/android-tutorial-view-viewgroup-intro.html 1,View和ViewGroup。 Android里的图形界面都是由View和ViewGroup以及他们的子类构成的:View:所有可视化控件的父类,提...

m0_38012497的博客 496

Android六大网络框架

Android六大网络框架分别为:Android-async-http(AsyncHttpClient)、OkHttp(OkHttpClient)、Retrofit、Volley、XUtils、Afinal      我们分别来讲一讲每个框架的具体详情:       1、volley  项目地址 https://github.com/smanikandan14/Volley-dem

Perpetual1006的博客 901

Android 六大框架

1、volley  项目地址 https://github.com/smanikandan14/Volley-demo  (1)  JSON,图像等的异步下载;  (2)  网络请求的排序(scheduling)  (3)  网络请求的优先级处理  (4)  缓存  (5)  多级别取消请求  (6)  和Activity和生命周期的联动(Activity结束时同时取消所有网

qq_35823924的博客 429
上一篇: 1.1 View与ViewGroup
下一篇: 1.3 Android中的几种UI排布方法介绍
WillFlow
博客等级 码龄11年 61粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值