前言
Lesson 1中包含三大部分内容:
- 如何根据需求选择对应的View(展示图片:ImageView 展示文本:TextView)
- 如何修改View的样式(字体颜色、图片的缩放裁剪)
- 接下来就来讲讲这第三小节的内容:如何将多个View按照需求在屏幕上进行摆放
引入
市面上每个应用的界面都是由许多的View组合而成的(QQ 微信 微博)那么这就涉及到整个布局中的View如何去进行摆放?
ViewGroup
ViewGroup能够把View摆放在特定的位置(上or下or中……)
通过例子说明:
上次课中的例子都是只对单独的某个View作说明
尝试着再拷贝一份TextView元素放到下面,你会发现出现了错误
注意:根View有且仅有一个,想要放置多个View时根View必须为一个ViewGroup
ViewGroup也属于View的一种,是屏幕上的一块矩形,ViewGroup包含于View,View包含ViewGroup
图中可以看到ViewGroup同样有宽高、背景颜色等属性 不难理解因为ViewGroup属于View
当然ViewGroup通常都是透明的即用户看不见的
可以把ViewGroup理解为View的容器
一个View包含着其他的View,前者为父View,后者叫子View,后者之间称兄弟View
? 看图提问 ?
答案在文章底部公布
到目前为止,我们已经知道了 想要放置多个View在屏幕上就必须把它们放到ViewGroup里
ViewGroup的类型
ViewGroup有很多种,每种ViewGroup都有其包含视图的规则,先介绍两种最最最常用的ViewGroup
LinearLayout(线性布局)
LinearLayout就是一个ViewGroup
规则:子视图称线性排列故称线性布局,所谓线性即水平或竖直
理论结束,看代码如何编写
ViewGroup使用单独的关闭标签,子视图书写在ViewGroup的开始标签和结束标签之间
LinearLayout的方向通过其属性: android:orientation 指定,
其值有二: vertical竖直方向、horizontal水平方向
特别注意:如果你不知道orientation属性是干嘛的,那你会怎么办?问别人? 千万别,你应该直接去百度或谷歌一下,肯定有你要的答案。 这里我想告诉大家的是要学会通过搜索引擎去解决问题。这种事以后还多着呢!
照着上图给你的代码去XMLV练习一下,尝试着增加一些子视图和更改它们的排列方向。
命名空间:XML命名空间声明,使用命名空间来指定所有的android属性,为什么使用android:前缀就是这个原因,特指示android系统自带的属性,其实前面也说过我们是可以自定义属性的,自定义属性时,前缀就是我们自定义的某个文本而非android了。 android: 是用来区分这些都是Android系统自带的属性
所以务必在根视图的开始标签中加上XML命名空间的声明
LinearLayout的宽高
- xxdp(固定宽高 xx具体指某个数值)
- 当内容的大小大于视图所设置的宽高时,会显示不全(被切掉一部分)
- wrap_content (包裹内容)
- 视图大小 == 内容大小
- match_parent(匹配父布局)
- 无论视图宽高为多少,视图与父布局均等宽/高
注意一种场景: 当前线性布局方向为horizontal(竖直方向),若有其中一个子视图的高度为match_parent,那么这个子视图将把它下面的子视图都顶出父布局之外(不可见)自己占据父布局剩下的高度,同理宽度亦然。
线性布局 - 屏幕适配
运行Android系统的设备千千万万,设备的屏幕大小、屏幕分辨率各式各样。
由此就会产生一个问题: 应用在不同设备上所显示的效果千差万别!
就如下图所示,分别在纵向放置、横向放置、大屏设备上显示的效果会不尽人意,三个TextView都挤到左上角了,这对于使用大屏设备的用户来说是尤为不人性化 也就是所说的用户体验极差。
需求 如果想要让这三个TextView无论在什么设备上都平均在屏幕的上中下的位置需要怎么做呢?
尝试用我们学过的知识:
- 每个TextView使用固定的高度均分屏幕大小?
- 只能针对某一个分辨率的屏幕,不能适配所有的屏幕大小
- 使用wrap_content?
- 包裹内容就如上图所示
- 使用match_parent?
- 匹配父元素会将剩余的兄弟师傅挤出父布局之外(无法看见)
以上做法都不能实现适配所有的设备,肿么办?问人? 不! 问人之前先百度/谷歌!!!
或者可以直接去安卓官方文档查找LinearLayout的属性 相信你能自己解决!
Layout Weight (布局权重)
布局权重:在线性布局中给各个子视图按比例分配空间,注意:仅在LinearLayout中有权重的概念
权重的使用
步骤一:
- 当父布局(线性布局)的方向为水平方向(horizontal)时
- android:layout_width="0dp" 把宽度设置为0dp
- 当父布局(线性布局)的方向为竖直方向(vertical)时
- android:layout_height="0dp" 把高度设置为0dp
步骤二:
- android:layout_weight="xx" 给每个子视图分配权重 xx为某个数值
权重越大,分配的空间越大
实现均分只需分配相等的权重即可
同理大家可以自己去实现水平方向的均分
来些应用例子
线性布局的东西到此结束!
RelativeLayout(相对布局)
相对布局相对于线性布局而言,更加灵活,方便。
规则:子视图与父布局(父视图)相对排列,或 子视图之间相对排列
代码如何编写?
子视图与父布局(父视图)相对排列
android:layout_alignParentTop="true" <!--与父布局的上边对齐-->
android:layout_alignParentBottom="true" <!--与父布局的下边对齐-->
android:layout_alignParentLeft="true" <!--与父布局的左边对齐-->
android:layout_alignParentRight="true" <!--与父布局的右边对齐-->
android:layout_centerInParent="true" <!--(水平竖直都)居中于父布局-->
android:layout_centerHorizontal="true" <!--水平居中于父布局-->
android:layout_centerVertical="true" <!--竖直居中于父布局-->
<!--上述属性值默认为false-->
示例
<?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:text="左上"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="右上"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="左中"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="右中"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="左下"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="右下"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="上中"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="下中"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
<TextView
android:text="正中"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge" />
</RelativeLayout>
子视图之间相对排列
android:layout_toLeftOf="@id/xxx" <!--在id为xxx的视图的左侧-->
android:layout_toRightOf="@id/xxx" <!--在id为xxx的视图的右侧-->
android:layout_below="@id/xxx" <!--在id为xxx的视图的下方-->
android:layout_above="@id/xxx" <!--在id为xxx的视图的上方-->
android:layout_alignTop="xxx" <!--上边缘与id为xxx的视图对齐-->
android:layout_alignBottom="xxx" <!--下边缘与id为xxx的视图对齐-->
android:layout_alignLeft="@id/xxx" <!--左边缘与id为xxx的视图对齐-->
android:layout_alignRight="xxx" <!--右边缘与id为xxx的视图对齐-->
说明: 每个视图都可以设置id属性作为唯一标识
android:id="@+id/xxx" <!--@+id 表示声明一个id属性-->
android:layout_toLeftOf="@id/xxx" <!--@id 引用某个已声明的id属性对应的视图,在id为xxx的视图左边-->
示例
<?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">
<Button
android:id="@+id/btn_up"
android:text="上"
android:layout_above="@id/btn_center"
android:layout_alignLeft="@id/btn_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
<Button
android:id="@+id/btn_center"
android:text="中"
android:layout_toRightOf="@id/btn_left"
android:layout_above="@id/btn_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
<Button
android:id="@+id/btn_down"
android:text="下"
android:layout_alignLeft="@id/btn_center"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
<Button
android:id="@+id/btn_left"
android:text="左"
android:layout_alignTop="@id/btn_center"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
<Button
android:id="@+id/btn_right"
android:text="右"
android:layout_toRightOf="@id/btn_center"
android:layout_alignTop="@id/btn_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
<Button
android:id="@+id/btn_hand"
android:text="拳"
android:layout_alignBottom="@id/btn_foot"
android:layout_toLeftOf="@id/btn_foot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
<Button
android:id="@+id/btn_foot"
android:text="脚"
android:layout_alignBottom="@id/btn_center"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"/>
</RelativeLayout>
代码结合上面的属性说明与效果图对比学习。
再来看一个常见的例子,QQ好友列表项的布局
动手写一下布局吧,相信你可以的
<?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="wrap_content">
<ImageView
android:id="@+id/iv_icon"
android:src="@mipmap/ic_launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_name"
android:text="树懒"
android:layout_toRightOf="@id/iv_icon"
android:textAppearance="?android:textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_text"
android:text="[在线] 时间冲淡了我的咖啡"
android:textColor="@android:color/darker_gray"
android:layout_toRightOf="@id/iv_icon"
android:layout_below="@id/tv_name"
android:textAppearance="?android:textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_signal"
android:text="4G"
android:layout_alignParentRight="true"
android:textColor="@android:color/darker_gray"
android:textAppearance="?android:textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
代码显示效果如下图
是不是感觉View都挤到一起了很难看 - -!
不足: 这些View都紧挨着父布局的边缘,这样显示给用户的感觉非常的不好。
怎么样给视图周围留出一些空白呢?
Padding & Margin (内边距 & 外边距)
用图说话
根据上图可以清楚的看到Padding 和Margin之间的区别
- Padding 内边距:View与View的内容之间的边距
- Margin 外边距 : 整个View与父布局之间的边距
在实际开发中由于视图的背景一般都为透明,所以二者之间看起来并无差别
android:padding="xxdp" <!--上下左右的内边距为xxdp-->
android:paddingTop="xxdp" <!--上边的内边距为xxdp-->
android:paddingBottom="xxdp" <!--下边的内边距为xxdp-->
android:paddingLeft="xxdp" <!--左边的内边距为xxdp-->
android:paddingRight="xxdp" <!--右边的内边距为xxdp-->
android:layout_margin="xxdp" <!--上下左右的外边距为xxdp-->
android:layout_marginTop="xxdp" <!--上边的外边距为xxdp-->
android:layout_marginBottom="xxdp" <!--下边的外边距为xxdp-->
android:layout_marginLeft="xxdp" <!--左边的外边距为xxdp-->
android:layout_marginRight="xxdp" <!--右边的外边距为xxdp-->
据此修改上面写的QQ好友列表项的代码如下
<?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="wrap_content"
android:padding="8dp"> <!-- 给整个布局添加内边距 -->
<ImageView
android:id="@+id/iv_icon"
android:src="@mipmap/ic_launcher"
android:layout_marginRight="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <!-- 给图片添加右边的外边距 -->
<TextView
android:id="@+id/tv_name"
android:text="树懒"
android:layout_toRightOf="@id/iv_icon"
android:textAppearance="?android:textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_text"
android:text="[在线] 时间冲淡了我的咖啡"
android:textColor="@android:color/darker_gray"
android:layout_toRightOf="@id/iv_icon"
android:layout_below="@id/tv_name"
android:textAppearance="?android:textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_signal"
android:text="4G"
android:layout_alignParentRight="true"
android:textColor="@android:color/darker_gray"
android:textAppearance="?android:textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
至于边距应该设置为多少合适,参照Meterial Design 设计规范:
http://wiki.jikexueyuan.com/project/material-design/
规范中推荐为8dp的倍数。