课程 1B: 打造布局

这节课是 Android 开发(入门)课程 的第一部分《布局和交互》的第二节课,导师依然是 Katherine Kuan 和 Kunal Chawla,主要内容是应用 Android 学习方法与 ViewGroups。

关键词:ViewGroups,LinearLayout 样式,RelativeLayout 样式,stack overflow,布局权重 layout_weight,Views ID,内边距 padding,外边距 layout_margin

应用 Android 学习方法
  1. 课程介绍了 XML 可视化编辑器 (XMLV,XML Visualizer),这个工具可以直接在网页显示 XML 的显示效果,不过根据我的尝试,XMLV 存在 bugs,会出现代码正确而仿真结果不正确的情况;同时它仅支持一部分 XML 代码,所以尽量不要尝试课程以外的代码。
  2. 通过 Android 文档找到帮助
    善用 Google 搜索和浏览器的查找 (ctrl/cmd+F) 功能可以通过 Android 文档找到帮助。例如要弄懂 android:orientation 这个属性,可以 Google 搜索 "android orientation",点击 "LinearLayout | Android Developers" 直接跳到 LinearLayout 的页面,再用浏览器查找 "orientation" 就可以找到说明文档。
  3. 通过论坛找到帮助
    遇到问题时可以直接将问题用 Google 搜索,也许有不少问答社区或论坛已经有相应的讨论。例如要知道如何将三个 TextView 在屏幕上平均分布,可以 Google 搜索 "linearlayout equally spaced children",第一个结果就是 stack overflow 问答社区的相应问题讨论,找到回答中的关键字 "layout_weight",再通过 Android 文档找到说明,看是否能解决问题。如果论坛中没有讨论,也可以尝试第一个提出问题。
  4. 学习阅读 Android 文档
    首次阅读 Android 文档时可能会对其中的术语或概念不熟悉,这时可通过词典或 Google 搜索查询学习,争取每次回头再看时能有越来越深入的理解。
  5. 仔细阅读代码,想象其在设备上的结果。
  6. 练习,通过练习能找到知识点的理解漏洞或偏差。
ViewGroups 的使用

ViewGroups也是一种 Views,拥有 Views 的属性,如矩形、边界不可见,宽度、高度、背景色等。ViewGroups 作为根 Views (Root Views) 包含了其他 Views,并将不同的 Views 摆放在屏幕上的不同位置。
按家谱描绘方式 (the Family Language),ViewGroups 被称为父 Views (the Parent Views),其他 Views 被称为子 Views (the Child Views),子 Views 之间可互称兄弟 Views (the Sibling Views)。
课程 1B 介绍了 RelativeLayout 和 LinearLayout 两种 ViewGroups。

首先来看 LinearLayout,他可以将子 Views 垂直排列 (Vertical Column) 或水平摆放 (Horizontal Row)。以下是一段 LinearLayout 代码。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F44336">

    <TextView
        android:text="Hi!There."
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:textSize="34sp" 
        android:background="#2196F3"/>

    <TextView
        android:text="This is Tom."
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:textSize="34sp" 
        android:background="#9C27B0"/>

    <TextView
        android:text="Nice to meet you."
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="3"
        android:textSize="34sp"
        android:background="#4CAF50"/>
</LinearLayout>

在 XMLV 的仿真效果如下图。

浏览整段代码,第一行和最后一行是 LinearLayout 的单独标签,它包含了三个 TextView。

  1. 阅读第一句:xmlns:android="http://schemas.android.com/apk/res/android"
    该属性特指给 Android 的 URL 速记,指定以 android: 开头的属性都属于 Android。这被称为 XML 命名空间声明 (XML NameSpace Declaration),xmlns 即 XML NameSpace 的缩写。XML 命名空间声明可自定义。有了不同的前缀,属性名相同时,XML 也不会产生冲突。

  2. 阅读第二句:android:orientation="vertical"
    该属性定义了 LinearLayout 对子 Views 的布局方式,实际值可以是垂直 (vertical) 或水平 (horizontal)。

  3. 阅读第三句和第四句:

    android:layout_width="match_parent"
    android:layout_height="match_parent"

这两个属性分别定义了 LinearLayout 的宽度和高度,实际值由指定 dp 值和 "warp_content" 之外出现了新值 "match_parent",对于 LinearLayout 这种根 Views 而言就将 LinearLayout 变成与设备屏幕等宽等高。

  1. 阅读第五句:android:background="#F44336"
    该属性定义了 LinearLayout 的背景色,结合第三句和第四句证明了 LinearLayout 也是一种 Views,拥有 Views 的属性。

  2. 观察第一个 TextView,其中第二句 android:layout_width="match_parent" 也使用了 "match_parent",对于这种子 Views 而言就将 TextView 变成与 LinearLayout 这种父 Views 等宽。

  3. 观察三个 TextView,发现 android:layout_height=“0dp”android:layout_weight 属性成对出现,这是将父 Views 中的子 Views 根据权重布局。
    (1)android:layout_height="0dp"
    将子 Views 的初始高度设置为 0,注意不要忘记单位 dp
    (2)android:layout_weight
    该属性定义了子 Views 的布局权重,真实值可以是任意自然数,默认为0,数字越大,权重越大。例如上面三个 TextView 中,权重分别是 1、2、3,仿真图中他们所占的高度分别是 1/6、2/6、3/6。父 Views 中只有一个子 Views 指定了权重时数值大小无所谓,但习惯为1。

阅读所有代码后,可总结出属性名有两种形式:
(1)单段式:text、textSize、background 这一类属性由子 Views 处理;
(2)两段式:layout_width、layout_height、layout_weight 这一类属性属于 layout 属性,由父 Views 使用来确定子 Views 的参数。
例如上述的 layout_weight 在 TextView 中并未指定是宽度的权重还是高度的,这是因为 layout_weight 是由父 Views (LinearLayout) 使用的,若 LinearLayout 对子 Views 的布局方式 (orientation) 是垂直 (vertical),那么对子 Views 进行高度上的权重布局;若为水平 (horizontal) 则对子 Views 进行宽度上的权重布局。

接下来看 RelativeLayout,它可以将子 Views 相对父 Views 摆放(上下左右中)和相对兄弟 Views(上下左右)摆放。以下是一段 RelativeLayout 代码。

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F44336">

    <TextView
        android:text="This is Tom."
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="34sp" 
        android:background="#2196F3"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:id="@+id/textview0"/>

    <TextView
        android:text="Hi!There."
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="34sp" 
        android:background="#9C27B0"
        android:layout_toLeftOf="@id/textview0"/>
</RelativeLayout>

在 XMLV 的仿真效果如下图。

浏览整段代码,第一行和最后一行是 RelativeLayout 的单独标签,他包含了两个 TextView。与 LinearLayout 相比,RelativeLayout 没有布局方式 (orientation) 这个属性。

  1. 观察第一个 TextView,它相对父 Views 放置,属性有
相对位置 属性名
android:layout_alignParentTop
android:layout_alignParentBottom
android:layout_alignParentLeft
android:layout_alignParentRight
水平居中 android:layout_alignParentHorizontal
垂直居中 android:layout_alignParentVertical

真实值为真 (true) 或假 (false),默认位置在父 Views 的左上角。属性可组合使用,如第一个 TextView 放置在 RelativeLayout 的右上角。

  1. 观察第二个 TextView,他相对第一个 TextView 这个兄弟 Views 放置,属性有
相对位置 属性名
android:layout_toLeftOf
android:layout_toRightOf
android:layout_above
android:layout_below

真实值为兄弟 Views 的 id,这就需要首先为其声明 id。如第一个 TextView 中 android:id="@+id/textview0" 就是给其取 Views ID,其中
(1)@: 表示 Android App 资源;
(2)+: 表示首次声明;
(3)id: 表示资源类型;
(4)textview0: Views ID,不能有空格,不能以符号开头(数字可以),应保持唯一性

android:layout_toLeftOf="@id/textview0"

第二个 TextView 放在第一个 TextView 的左边,属性的真实值为第一个 TextView 的 ID,其中 @ 与 id 之间没有 +。第一个 TextView 相对于第二个 TextView 而言也称为锚定 Views (the Anchor Views)。

Views 视觉润色

介绍了 RelativeLayout 和 LinearLayout 两类 ViewGroups 后,课程 1B 还简要介绍了为 Views 视觉润色的方法,即在 Views 之间添上空间,利用 padding 或 margin 属性。以下是一段 padding 和 margin 的代码。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#F44336">

    <TextView
        android:text="Hi there!"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="45sp"
        android:background="#009688"
        android:paddingTop="16dp"
        android:paddingLeft="32dp"
        android:paddingBottom="16dp"
        android:paddingRight="32dp"
        android:layout_marginLeft="32dp"
        android:layout_marginTop="32dp"/>
</LinearLayout>

在 XMLV 的仿真效果如下图。

  1. margin 属性会使子 Views 距离父 Views 中的指定位置有间隔,不会改变子 Views。属性有 android:layout_margin,或分成上下左右四个方向,android:layout_marginLeftandroid:layout_marginRightandroid:layout_marginTopandroid:layout_marginBottom,可组合使用。注意 margin 属于 layout 属性,由父 Views 处理。真实值默认为 0。
    如上面的 TextView 距离其在 LinearLayout 中默认左上角位置左边和上边分别距离 32dp。

  2. padding 属性会使 Views 内的内容距离指定位置有间隔,例如上述 TextView 内的文字距离 TextView 上下边界有 16dp、左右边界有 32dp。属性有 android:padding,或分成上下左右四个方向,android:paddingTopandroid:paddingBottomandroid:paddingLeftandroid:paddingRight,可组合使用。真实值默认为0。

  3. padding 和 margin 的真实值设置一般为 8dp 的倍数,具体可参考 Material Design

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343