Android从入门到精通
Chapter 02 用户界面设计基础
2.1 UI设计相关的概念
我们要开发的Android应用时运行在手机或者平板电脑上的程序,这些程序给用户的第一印象就是用户界面,也就是User Interface,简称UI。在Android中,进行用户界面设计可以称为UI设计,在进行UI设计时,经常会用到View和View Group。对于初识Android的人来说,一般不好理解。下面对这里两个概念进行详细介绍。
2.1.1 View
View在Android中可以理解为视图。它占据屏幕上的一个矩形区域,负责提供组件绘制和事件处理的方法。如果把Android界面比喻成窗户,那么每块玻璃都是一个View。View类是所有UI组件(Android默认创建的界面中的TextView就是UI组件)的基类。
说明:View类位于android.view包中;文本框组件TextView是View类的子类,位于android.widget包中。
在Android中,View类及其子类的相关属性,既可以在XML布局文件中进行设置,也可以通过成员方法在java代码中动态设置。View类常用的属性及对应的方法如下:
XML属性 | 方法 | 描述 |
---|---|---|
android:background | setBackGroundResource(int) | 设置背景,其属性值为Drawable资源或者颜色值 |
android:clickable | setClicked(boolean) | 设置是否响应单击事件,其属性值为boolean型的true或者false |
android:elevation | setElevation | Android API 21新添加的,用于设置z轴的深度,其属性值为带单位的有效浮点数 |
android:id | setId(int) | 设置组件的唯一标识符ID,可以通过findViewById()方法获取 |
android:longClickable | setLongClickable(boolean) | 设置是否响应长单击事件,其属性值为boolean型的true或者false |
android:minHeighgt | setMinimumHeight(int) | 设置最小高度,其属性值为带单位的整数 |
android:minWidth | setMinimumWidth(int) | 设置最小宽度,其属性值为带单位的整数 |
android:onClick | 设置单击事件触发的方法 | |
android:padding | setPaddingRelative(int, int, int, int) | 设置4个边的内边距 |
android:paddingBottom | setPaddingRelative(int, int, int, int) | 设置底边的内边距 |
android:paddingEnd | setPaddingRelative(int, int, int, int) | 设置右边的内边距 |
android:paddingLeft | setPadding(int, int, int, int) | 设置左边的内边距 |
android:paddingRight | setPadding(int, int, int, int) | 设置右边的内边距 |
android:paddingStart | setPaddingRelative(int, int, int, int) | 设置左边的内边距 |
android:paddingTop | setPaddingRelative(int, int, int, int) | 设置顶边的内边距 |
android:visibility | setVisibility(int) | 设置View的可见性 |
2.1.2 ViewGroup
ViewGroup在Android中代表容器。如果还用窗户来比喻的话,ViewGroup相当于窗户框,用户控制玻璃的安放。ViewGroup类继承自View类,它是View类的扩展,是用来容纳其他组件的容器,但是由于ViewGroup是一个抽象类,所以在实际应用中通常是使用ViewGroup的子类来做容器的,例如,布局管理器。
ViewGroup控制器子组件的分布时(例如,设置子组件的内边距、宽度和高度等),还经常依赖于ViewGroup.LayoutParams和ViewGroup.MarginLayoutParams两个内部类,下面分别介绍。
1. ViewGroup.LayoutParams类
ViewGroup.LayoutParams类封装了布局的位置、高和宽等信息。它支持android:layout
_height和android:layout_width两个XML属性,它们的属性值,可以使用精确的数值,也可以使用**fill_parent(表示与父容器相同)、match_parent(表示与父容器相同,需要API 8或以上版本才支持)和wrap_content(表示包裹其自身的内容)**指定。
2. ViewGroup.MarginLayoutParams类
ViewGroup.MarginLayoutParams类用于控制器子组件的外边距,它支持的常用属性如下表:
XML属性 | 描述 |
---|---|
android:layout_marginBottom | 设置底外边距 |
android:layout_marginEnd | 该属性为Android4.2新增加的属性,设置右外边距 |
android:layout_marginLeft | 设置左外边距 |
android:layout_marginRight | 设置右外边距 |
android:layout_marginStart | 该属性为Android4.2新增加的属性,设置左外边距 |
android:layout_marginTop | 设置顶外边距 |
在Android中,所有的UI界面都是由View类行尾ViewGroup类及其子类组合而成的。在ViewGroup类中,除了可以包含普通的View类外,还可以再次包含ViewGroup类。实际上,这使用了Composite(组合)设计模式。
3. 内边距与外边距
2.2 控制UI界面
2.2.1 使用XML布局文件控制UI界面
Android提供了一种非常简单、方便的方法用于控制UI界面。该方法采用XML文件来进行界面布局,从而将布局界面的代码和逻辑控制的Java代码分离来,使程序的结构更加清晰、明了。
使用XML布局文件控制UI界面可以分为以下两个关键步骤。
-
在Android应用的res\layout目录下创建XML布局文件,该布局文件的名称可以采用任何符合Java命名规则的文件名。
-
在Activity中使用以下Java代码显示XML文件中布局的内容。
setContentView(R.layout.activity_main);
在上面的代码中,activity_main使XML布局文件的文件名
通过上面的步骤就可以轻松实现布局并显示UI界面的功能。
2.2.2 开发自定义的View
一般情况下,开发Android应用程序的UI界面不直接使用View类和ViewGroup类,而是使用这两个类的子类。例如,要显示一个图片,就可以使用View类的子类ImageView。虽然Android提供了很多继承了View类的UI组件,但是在实际开发中,还会出现不足以满足程序需求的情况。这时,我们就可以通过继承View类来开发自己的组件。开发自定义的View组件大致分为以下三个步骤。
-
创建一个继承android.view.View类的Java类,并且重写构造方法。
PS:在自定义的View类中,至少需要重写一个构造方法。
-
根据需要重写其他的方法。被重写的方法可以通过下面的方法找到。
在代码中右击 ——> 在弹出的快捷菜单中选择Generate命令 ——> 再从弹出的菜单中选择Override Methods…命令,将显示可以被重写的所有方法 ——> 选择需要重写的方法,并单击OK按钮。
完成上述步骤,Android Studio将自动重写指定的方法。通常情况下,不需要重写全部的方法。
-
在项目的活动中,创建并实例化自定义View类,然后将其添加到布局管理器中。
下面通过一个小例子来演示如何开发自定义的View:
-
修改res\layout节点下的布局文件activity_main.xml,将默认创建的布局管理器修改成帧布局管理器FrameLayout,并且设置背景和id属性,然后将TextView组件删除。修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout 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:background="@mipmap/grass" android:id="@+id/mylayout" android:paddingBottom="16dp" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="16dp" tools:context=".MainActivity"> </FrameLayout>
-
在com.example包上右击,在弹出的快捷菜单中选择View->Java Class命令,新建一个名称为RabbitView的Java类,该类继承自android.view.View类,重写带一个参数Context的构造方法和onDraw()方法。其中,在构造方法中设置兔子的默认显示位置,在onDraw()方法中根据图片绘制小兔子。RabbitView类的关键代码如下:
public class RabbitView extends View { public float bitmapX; public float bitmapY; public RabbitView(Context context) { super(context); bitmapX = 210; bitmapY = 130; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); //创建并实例化Paint对象 Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.mipmap.rabbit); //根据图片生成位图对象 canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint); //绘制小兔子 if(bitmap.isRecycled()) { //判断图片是否回收 bitmap.recycle(); //强制回收图片 } } }
-
在MainActivity的onCreate()方法中,首先获取帧布局管理器,并实例化小兔子对象rabbit,然后为rabbit添加触摸事件监听器,在重写的触摸事件中设置rabbit的显示位置,并重绘rabbit组件,最后将rabbit添加到布局管理器中,关键代码如下:
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.mylayout); //获取帧布局管理器 final RabbitView rabbit = new RabbitView(this); //创建并实例化RabbitView //为小兔子添加触摸事件监听 rabbit.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { rabbit.bitmapX = event.getX(); rabbit.bitmapY = event.getY(); rabbit.invalidate(); return true; } }); frameLayout.addView(rabbit);
2.3 布局管理器
在Android中,每个组件在窗体中都有具体的位置和大小,在窗体中摆放各种组件时,很难进行判断。不过,使用Android布局管理器可以很方便地控制组件的位置和大小。Android提供了以下5种布局管理器。
- 相对布局管理器(RelativeLayout):通过相对定位的方式来控制组件的摆放位置。
- 线性布局管理器(LinearLayout):是指在垂直或水平方向上依次摆放组件。
- 帧布局管理器(FrameLayout):没有任何定位方式,默认情况下,所有的组件都会摆放在容器的左上角,逐个覆盖。
- 表格布局管理器(TableLayout):使用表格的方式按行、列来摆放位置。
- 网格布局管理器(GridLayout):通过它可以实现跨行或跨列摆放组件。
Android提供的布局管理器均直接或间接地继承自ViewGroup。因此,所有的布局管理器都可以作为容器使用,我们可以像布局管理器中添加多个UI组件。当然,也可以将一个或多个布局管理器嵌套到其他的布局管理器中。
2.3.1 相对布局管理器
相对布局管理器是通过相对定位的方式让组件出现在布局的任何位置。
在Android中,可以在XML布局文件中定义相对布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义相对布局管理器。在XML布局文件中,定义相对布局管理器可以使用<RelativeLayout>标记,其基本的语法格式如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</RelativeLayout>
在上面的语法中,<RelativeLayout>为起始标记;</RelativeLayout>为结束标记。在起始标记中的xmlns:android为设置XML命名空间的属性,其属性值为固定写法。
说明:在Android中,无论是创建哪一种布局管理器都有两种方法,一种是在XML布局文件中定义,另一种是使用Java代码来创建。推荐使用的是XML布局文件中定义。
RelativeLayout支持的常用XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:gravity | 用户设置布局管理器中各子组件的对齐方式 |
android:ignoreGravity | 用于指定哪个组件不受gravity属性的影响 |
在相对布局管理器中,只有上面介绍的两个属性是不够的,为了更好地控制该部件管理器中各子组件的布局分布,RelativeLayout提供了一个内部类RelativeLayout.LayoutParams,通过该类提供的大量XML属性,可以很好地控制相对布局管理器中各组件的分布方式。RelativeLayout.LayoutParams支持的XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:layout_above | 其属性值为其他组件的id属性,用于指定该组件位于哪个组件的上方 |
android:layout_below | 其属性值为其他组件的id属性,用于指定该组件位于哪个组件的下方 |
android:layout_alignBottom | 其属性值为其他组件的id属性,用于指定该组件位于哪个组件的下边界对齐 |
android:layout_alignLeft | 其属性值为其他组件的id属性,用于指定该组件位于哪个组件的左边界对齐 |
android:layout_alignRight | 其属性值为其他组件的id属性,用于指定该组件位于哪个组件的右边界对齐 |
android:layout_alignTop | 其属性值为其他组件的id属性,用于指定该组件位于哪个组件的上边界对齐 |
android:layout_alignParentBottom | 其属性值为boolean值,用于指定该组件是否与布局管理器底端对齐 |
android:layout_alignParentLeft | 其属性值为boolean值,用于指定该组件是否与布局管理器左边对齐 |
android:layout_alignParentRight | 其属性值为boolean值,用于指定该组件是否与布局管理器右边对齐 |
android:layout_alignParentTop | 其属性值为boolean值,用于指定该组件是否与布局管理器顶端对齐 |
android:layout_centerHorizontal | 其竖向只为boolean值,用于指定该组件是都位于布局管理器水平居中的位置 |
android:layout_centerInParent | 其竖向只为boolean值,用于指定该组件是都位于布局管理器中央位置 |
android:layout_centerVertical | 其竖向只为boolean值,用于指定该组件是都位于布局管理器垂直居中的位置 |
android:layout_toLeftOf | 起属性值为其他UI组件的id属性,用于指定该组件位于哪个组件的左侧 |
android:layout_toRightOf | 起属性值为其他UI组件的id属性,用于指定该组件位于哪个组件的右侧 |
下面编写一个小例子(软件更新提示界面)来进行演示:
<RelativeLayout 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="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发现有Widget的新版本,您想现在就安装吗?"
android:layout_centerInParent="true"/>
<Button
android:id="@+id/updateNow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="现在更新"
android:layout_centerHorizontal="true"
android:layout_below="@+id/textView"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="以后再说"
android:layout_below="@+id/textView"
android:layout_toRightOf="@+id/updateNow"/>
</RelativeLayout>
2.3.2 线性布局管理器
线性布局管理器是将放入其中的组件按照垂直或水平方向来布局,也就是控制放入其中的组件横向排列或纵向排列。其中,纵向排列的成为垂直线性布局管理器;横向排列的成为水平布局管理器。在垂直线性布局管理器中,每一行只能放一个组件,而在水平线性布局管理器中,每一列只能放一个组件。另外,Android的线性布局管理器中的组件不会换行,当组件一个挨着一个排列到窗体的边缘后,剩下的组件将不会被显示出来。
在XML布局文件中,定义线性布局管理器可以使用<LinearLayout>标记,其基本的语法格式如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</LinearLayout>
1. LinearLayout的常用属性
LinearLayout支持的常用XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:orientatin | 用于设置布局管理器内组件的排列方式,其可选值为horizontal和vertical,默认值为vertical。其中,horizontal表示水平排列,vertical表示垂直排列 |
android:gravity | android:gravity属性用于设置布局管理器内组件的显示位置,其可选值包括:top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical和clip_horizontal。这些属性值也可以同时指定,各属性值之间用竖线“|”隔开(前后不能有空格)。例如要指定组件靠右下对齐,可以使用属性值right|bottom |
android:layout_width | 用于设置该组件的基本宽度,其可选值有fill_parent、match_parent和wrap_content |
android:layout_height | 用于设置该组件的基本高度,其可选值有fill_parent、match_parent和wrap_content |
android:id | 用于为当前布局管理器指定一个id属性,在Java代码中可以应用该属性单独引用这个布局管理器。为布局管理器指定id属性后,在R.java文件中,会自动派生一个对应的属性,在Java代码中,可以通过findViewById()方法来获取它 |
android:background | 用于为该组件设置背景。可以是图片,也可以是背景颜色,为组件指定背景图片时,可以将准备好的背景图片复制到drawable目录下,然后使用代码“android:background="@drawablw/background"”进行设置 如果想要指定背景颜色,可以使用颜色值,例如,要想指定背景颜色为白色,可以使用代码“android:background="#FFFFFFFF"” |
注意:在水平线性布局管理器中,子组件的android:layout_width属性通常不设置为match_parent或fill_parent,如果这样设置,在该布局管理器中一行只能显示一个组件;在垂直线性布局管理器中,android:layout_height属性值通常不设置为match_parent或fill_parent,如果这样设置,在该布局管理器中一列智能显示一个组件。
2. 子组件在LinearLayout中的常用属性
在LinearLayout中放置的子组件,还经常用到下表所示的两个属性:
XML属性 | 描述 |
---|---|
androidLlayout_gravity | 用于设置组件在其父容器中的位置。它的属性值与android:gravity属性相同,也是top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical和clip_horizontal。这些属性值也可以同时指定,各属性值之间用竖线“|”隔开,但竖线前后一定不能有空格 |
android:layout_weight | 用于设置组件所占的权重,即用于设置组件占父容器剩余空间的比例。该属性的默认值为0,表示需要显示多大的视图就占据多大的屏幕空间,当设置一个高于0的值时,则将父容器的剩余空间分割,分割的大小取决于每个组件的layout_weight属性值。例如,在一个320 x 480的屏幕中,放置一个水平线性布局管理器,并且在该布局管理器中放置两个组件,并且这两个组件的android:layour_weight属性值都设置为1,那么,每个组件将分配到父容器的1/2的剩余空间 |
↓↓↓
注意:在线性布局管理器中,使用android:layput_gravity属性放入其中的组件的摆放位置不起作用,要想实现这一功能,需要使用android:gravity属性。
下面编写一个小例子(登录微信界面)进行演示:
<LinearLayout 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="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:hint="QQ号/微信号/Emain"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:password="true"
android:hint="密码" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"
android:textColor="#000000"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录遇到问题?"
android:gravity="center_horizontal"
android:paddingTop="20dp"/>
</LinearLayout>
2.3.3 帧布局管理器
在帧布局管理器中,每加入一个组件都将创建一个空白的区域,通常称为一帧,默认情况下,这些帧都会被放置在屏幕的左上角,即帧布局的左上角(0, 0)坐标点开始布局。多个组件层叠排序,后面的组件覆盖前面的组件。
在XML布局文件中定义帧布局管理器可以使用<FrameLayout>标记,其基本的语法格式如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</FrameLayout>
FrameLayout支持的常用XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:foreground | 设置该帧布局管理器的前景图像 |
android:foregroundGravity | 定义绘制前景图像的gravity属性,即前景图像显示的位置 |
下面编写一个小例子(层叠的正方形)进行演示:
<FrameLayout 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="match_parent"
android:layout_height="match_parent"
android:foreground="@mipmap/rabbit"
android:foregroundGravity="bottom|right"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="280dp"
android:layout_height="280dp"
android:layout_gravity="center"
android:background="#FF0000FF"
android:textColor="#FFFFFF"
android:text="蓝色背景的TextView"/>
<TextView
android:id="@+id/textView2"
android:layout_width="230dp"
android:layout_height="230dp"
android:layout_gravity="center"
android:background="#FF0077FF"
android:textColor="#FFFFFF"
android:text="天蓝色背景的TextView"/>
<TextView
android:id="@+id/textView3"
android:layout_width="180dp"
android:layout_height="180dp"
android:layout_gravity="center"
android:background="#FF00B4FF"
android:textColor="#FFFFFF"
android:text="水蓝色背景的TextView"/>
</FrameLayout>
2.3.4 表格布局管理器
表格布局管理器与常见的表格类似,它以行、列的形式来管理放入其中的UI组件。表格布局管理器使用<TableLayout>标记定义。在表格布局管理器中,可以添加多个<TableRow>标记,每个<TableRow>标记,在<TableRow>标记占一行。由于<TableRow>标记也是容器,所以在该标记中还可添加其他组件,在<TableRow>标记中,每添加一个组件,表格就会增加一列。在表格布局管理器中,列可以被隐藏;也可以被设置为伸展的,从而填充可以利用的屏幕空间;还可以设置为强中收缩,直到表格匹配屏幕大小。
说明:如果在表格布局中,直接向<TableLayout>中添加UI组件,那么这个组件将独占一行。
在XML布局文件中定义表格布局管理器的基本语法如下:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
<TableRow 属性列表> 需要添加的UI组件啊 </TableRow>
多个<TableRow>
</TableLayout>
TableLayout继承了LinearLayout,因此它完全支持LinearLayout所支持的全部XML属性,此外,TableLayout还支持下表的XML属性:
XML属性 | 描述 |
---|---|
android:collapseColumns | 设置需要被隐藏的列的列序号(序号从0开始),多个列序号之间用逗号“,”分割 |
android:shrinkColumns | 设置需要被收缩的列的列序号(序号从0开始),多个列序号之间用逗号“,”分割 |
android:stretchColumns | 设置需要被拉伸的列的列序号(序号从0开始),多个列序号之间用逗号“,”分割 |
下面编写一个小例子(雅用户登录界面)进行演示:
2.3.5 网格布局管理器
网格布局管理器是在Android 4.0 版本中提出的,使用GridLayout表示。在网格布局管理器中,屏幕被虚拟的细线划分成行、列和单元格,每个单元格放置一个组件,并且这个组件也可以跨行或跨列摆放。
说明:网格布局管理器与表格布局管理器有些类似,都可以以行、列的形式管理放入其中的组件,但是它们之间最大的不同就是网格布局管理器可以跨行显示组件,而表格布局管理器则不能。
在XML布局文件中,定义网格布局管理器可以使用<GridLayout>标记,其基本的语法格式如下:
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
属性列表
>
</GridLayout>
GridLayout支持的常用XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:columnCount | 用于指定网格的最大列数 |
android:orientation | 用于当没有为放入其中的组件分配行和列时,指定其排列方式。其属性值为horizontal表示水平排列,vertical表示垂直排列 |
android:rowCount | 用于指定网格的最大行数 |
android:useDefaultMargin | 用于指定是否使用默认的编辑,其属性值设置为true时,表示使用;为false时,表示不使用 |
android:alignmentMode | 用于指定该布局管理器采用的对其模式,其属性值为alignBounds时,表示对齐边界;为alignMargins时,表示对齐边距,默认值为alignMargins |
android:rowOrderPreserved | 用于设置行边界显示的顺序和行索引的顺序是否相同,其属性值为true,表示相同;为false,表示不相同 |
android:columnOrderPreserved | 用于设置列边界显示的顺序和列索引的顺序是否相同,其属性值为true,表示相同;为false,表示不相同 |
为了控制网格布局管理器中各子组件的布局分布,网格布局管理器提供了GridLayout.LayoutParams内部类,在该类中提供了下表所示的XML属性,用于控制网格布局管理器中各组件的布局分布。
XML属性 | 描述 |
---|---|
android:layout_column | 用于指定该子组件位于网格的第几列 |
android:layout_columnSpan | 用于指定该子组件横向跨几列(索引从0开始) |
android:layout_columnWeight | 用于指定该子组件在水平方向上的权重,即该组件分配水平剩余空间的比例 |
android:gravity | 用于指定该子组件采用什么方式占据该网格的空间,其可选值有top(放置在顶部)、bottom(放置在底部)、left(放置在左侧)、right(放置在右侧)、center_vertical(垂直居中)、fill_vertical(垂直填满)、center_horizontal(水平居中)、fill_horizontal(水平填满)、center(放置在中间)、fill(填满)、clip_vertical(垂直剪切)、clip_horizontal(水平剪切)、start(放置在开始位置)、end(放置在结束位置) |
android:layout_row | 用于指定该子组件位于网格的第几行(索引从0开始) |
android:layout_rowSpan | 用于指定该子组件纵向跨几行 |
android:layout_rowWeight | 用于指定该子组件在垂直方向上的权重,即该组件分配迟滞剩余空间的比例 |
说明:在网格布局管理器中,如果想让某个组件跨行或跨列,那么需要先通过android:layout_columnSpan或者android:layout_rowSpan设置跨越的行数或列数,然后再设置其layout_gravity属性为fill,表示该组件填满跨越的行或者列。
下面编写一个小例子(聊天信息列表界面)进行演示:
<GridLayout 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="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:columnCount="6"
tools:context=".MainActivity">
<ImageView
android:id="@+id/boyChat1"
android:src="@mipmap/chatinfor2"
android:layout_gravity="end"
android:layout_columnSpan="4"
android:layout_column="1"
android:layout_row="0"
android:layout_marginRight="5dp"
android:layout_marginBottom="30dp"/>
<ImageView
android:id="@+id/boyHead1"
android:src="@mipmap/boyhead"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_column="5"
android:layout_row="0"/>
<ImageView
android:id="@+id/girlChat1"
android:src="@mipmap/chatinfor1"
android:layout_gravity="left"
android:layout_columnSpan="4"
android:layout_column="1"
android:layout_row="1"
android:layout_marginRight="5dp"
android:layout_marginBottom="30dp"/>
<ImageView
android:id="@+id/girlHead1"
android:src="@mipmap/girlhead"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_column="0"
android:layout_row="1"/>
<ImageView
android:id="@+id/boyChat2"
android:src="@mipmap/chatinfor2"
android:layout_gravity="end"
android:layout_columnSpan="4"
android:layout_column="1"
android:layout_row="2"
android:layout_marginRight="5dp"
android:layout_marginBottom="30dp"/>
<ImageView
android:id="@+id/boyHead2"
android:src="@mipmap/boyhead"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_column="5"
android:layout_row="2"/>
<ImageView
android:id="@+id/girlChat2"
android:src="@mipmap/chatinfor1"
android:layout_gravity="left"
android:layout_columnSpan="4"
android:layout_column="1"
android:layout_row="3"
android:layout_marginRight="5dp"
android:layout_marginBottom="30dp"/>
<ImageView
android:id="@+id/girlHead2"
android:src="@mipmap/girlhead"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_column="0"
android:layout_row="3"/>
<EditText
android:id="@+id/inputEditor"
android:layout_width="300dp"
android:layout_columnSpan="5"
android:layout_column="0"
android:layout_row="4"
android:hint="请输入待发送的消息"/>
<Button
android:id="@+id/submitButton"
android:text="发送"
android:layout_column="5"
android:layout_row="4"/>
</GridLayout>
2.3.6 布局管理器的嵌套
在进行用户界面设计时,很多时候只通过一种布局管理器很难实现想要的界面效果,这时就得将多种布局管理器混合使用,即布局管理器的嵌套。在实现布局管理器的嵌套时,只需要记住以下几个原则即可:
- 根布局管理器必须包含xmlns属性
- 在一个布局文件中,最多只能有一个根布局管理器。如果想要使用多个布局管理器,就需要使用一个根布局管理器将它们括起来
- 不能嵌套太深。如果嵌套太深,则会影响性能,主要会降低页面的加载速度
下面编写一个小例子(朋友圈界面)进行演示:
<LinearLayout 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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<ImageView
android:id="@+id/icon1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:src="@mipmap/boyhead"/>
<TextView
android:id="@+id/name1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/icon1"
android:text="爱新觉罗·胖橘"
android:textColor="#576B95"/>
<TextView
android:id="@+id/content1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/name1"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/icon1"
android:minLines="3"
android:text="嬛嬛,朕要diss你!"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_below="@+id/content1"
android:layout_toRightOf="@+id/icon1"
android:text="昨天"
android:textColor="#9A9A9A"/>
<Button
android:id="@+id/comment1"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@mipmap/comment"
android:layout_below="@id/content1"
android:layout_alignParentRight="true"/>
</RelativeLayout>
<!-- 显示一个分隔线 -->
<ImageView
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/black"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<ImageView
android:id="@+id/icon2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:src="@mipmap/girlhead"/>
<TextView
android:id="@+id/name2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/icon2"
android:text="安小鸟"
android:textColor="#576B95"/>
<TextView
android:id="@+id/content2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/name2"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/icon2"
android:minLines="3"
android:text="这样好的阳光,我怕是再也看不到了!"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_below="@+id/content2"
android:layout_toRightOf="@+id/icon2"
android:text="昨天"
android:textColor="#9A9A9A"/>
<Button
android:id="@+id/comment2"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@mipmap/comment"
android:layout_below="@id/content2"
android:layout_alignParentRight="true"/>
</RelativeLayout>
<!-- 显示一个分隔线 -->
<ImageView
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/black"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<ImageView
android:id="@+id/icon3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:src="@mipmap/girlhead"/>
<TextView
android:id="@+id/name3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/icon3"
android:text="端妃"
android:textColor="#576B95"/>
<TextView
android:id="@+id/content3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/name3"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/icon3"
android:minLines="3"
android:text="其实各花入各眼,是非只在人心罢了!"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_below="@+id/content3"
android:layout_toRightOf="@+id/icon3"
android:text="昨天"
android:textColor="#9A9A9A"/>
<Button
android:id="@+id/comment3"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@mipmap/comment"
android:layout_below="@id/content3"
android:layout_alignParentRight="true"/>
</RelativeLayout>
<!-- 显示一个分隔线 -->
<ImageView
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/black"/>
</LinearLayout>