第 章.1 Android UI 基本概念 用户界面 (User Interface,UI) 是用户与设备之间进行信息交流的直接媒介, 是决定用户体验最重要的部分 相比于早期的计算机的主要交互界面 批处理界面和命令行界面, 现在更为流行的是更简单直接的用户图形界面 (Graphical User Interface, GUI) GUI 简单易用, 受众面广, 直接推动了个人计算机的发展 目前, 主流大众的操作系统都采用了 GUI, 安卓也不例外 通常 GUI 上会放置各种组件, 这些组件通过巧妙的设计, 便能组成灵活美观的界面 Android 程序的 UI 组件分为 widget 控件和 layout 组件两大类, 这两类的根类都是 View 类 widget 控件 :UI 的最基本单位, 即不能在这类组件中放入其他 UI 组件 常见的 widget 组件有 Button( 按钮 ) TextView( 文本标签 ) EditText( 文字输入框 ) 等 layout 组件 : 布局组件, 像容器一般, 其中可以加入其他 layout 组件或 widget 组件 常用的 layout 组件有 LinearLayout( 线性布局 ) RelativeLayout( 相对布局 ) FrameLayout( 框架布局 ) TableLayout( 表格布局 ) GridLayout ( 网格布局 ) 等 View 类的常用 xml 文件元素属性如表 -1 所示 表 -1 View 类属性 属 性 对应方法 说 明 android.id setid(int id) 设置组件的标识符 android.background setbackground(int color) 设置背景颜色 android.visibility setvisibility(int) 设置组件的可见性 android.clickable setclickable(boolean) 设置组件是否响应单击事件 android.alpha setalpha(float) 设置组件的透明度
续表 属性对应方法说明 android.layout_weight android.layout_height setheight(int) setwidth(int) findviewbyid(int id) 设置组件的宽度, 一般有 match_parent 和 wrap_content 两个选项 设置组件的宽度, 一般有 match_parent 和 wrap_content 两个选项 与 id 对应的组件匹配 基于 MVC(Model-View-Controller) 模型,Android 程序开发采用界面设计与程序逻辑分离的策略 开发者应该使用 XML 文件对用户界面进行描述, 将资源文件独立保存在资源文件夹中 Android 的用户界面描述非常灵活, 允许定义用户界面组件的大小 位置 外观甚至触发事件 更上一层 MVC 模型包括处理用户输入的控制器 (Controller) 显示图像的视图 (View) 和模型 (Model) 模型是应用程序的核心, 数据和代码都保存在模型中 Android 的用户界面框架采用单线程用户界面 (Single-threaded UI) 的模式 在这种模式下, 控制器从事件队列中获取事件和视图在屏幕上绘制用户界面采用的是同一进程 因此, 用户不需要在控制器和视图之间进行同步, 而且所有事件的处理都是按照其加入事件队列的顺序进行的, 也就是事件处理函数具有原子性 但此模式也有弊端 子线程中不允许直接修改用户界面 而且如果事件处理函数过于复杂, 可能会使用户界面失去响应, 因此复杂的事件处理工作应该交给后台线程处理.2 基本控件.2.1 TextView TextView( 文本标签 ) 用于显示文本字符, 是最常用的 UI 组件之一, 支持多行文本和自动换行 常用的方法如下 : gettext() 获取文本标签的文本内容 ; settext(charsequence text) 设置文本标签的文本内容 ; settextsize(float size) 设置文本标签的文本大小 ; settext(int color) 设置文本标签的文本颜色 第 章
Android 程序设计 6 常用的 XML 文件元素属性如下 : android:text 文本标签的文本内容 ; android:textsize 文本标签的文本大小 ; android:textcolor 文本标签的文本颜色 ; android:typeface 文本标签的字体样式, 有 normal sans serif monospace 等选项 此外, 适用于 View 类的元素属性也适用于 TextView 等所有组件, 此处不再赘述 例 -1 演示 TextView 组件的使用方法 打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 TextViewDemo 打开界面布局文件 activity_main.xml Android Studio 已经自动在其中生成一个 Hello World! 的 Textview 切换到代码视图, 修改 activity_main.xml 的代码如下 : 1 2 4 5 6 7 8 9 10 11 12 1 14 15 <?xml version="1.0" encoding="utf-8"?> <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" > <TextView Android:id="+id/textView1" android:layout_width="wrap_content" android:textsize="20" android:text="string/textviewstring" /> </RelativeLayout> 本书后文代码中的所有省略号均表示由于篇幅所限, 部分内容省略不写 该布局文件添加了一个 TextView 组件 第 10 行表明为该组件增设一个 id 为 textview1 的 TextView; 第 11 12 行分别指定其宽度和高度 ; 第 1 行设置该文本标签的文本大小 ; 第 14 行指定其文本内容引用 string.xml 下的 textviewstring, 开发者也可以在布局文件中设置直接字符串, 而不引用字符串资源, 但这不利于复用和后期修改, 不推荐
在 value 目录下的 string.xml 中添加字符串资源 1 2 4 <resources> <string name="app_name">textviewdemo1</string> <string name="textviewstring">"textview 文本标签内容 "</string> </resources> 为了在代码中引用控件, 需要在代码中引入相应的 android.widget 开发包, 然后使用 findviewbyid(int id) 函数通过 id 引用该控件, 并将该控件赋值给创建的空间对象 如下编写代码, 将 TextView 的文本颜色改为红色 1 2 4 5 package com.example.textviewdemo; import android.graphics.color; import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.widget.textview; 6 7 8 9 10 11 12 1 14 15 public class MainActivity extends AppCompatActivity { TextView textview; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); textview=(textview)findviewbyid(r.id.textview); textview.settextcolor(color.red); } } 代码第 7 行声明了一个 TextView 组件对象 第 12 行使用 findviewbyid(int id) 函数关联到对应 id 的组件, 但该函数返回的组件类型是 View, 需要强制转换为 TextView 第 1 行, 通过调用 TextView 的 SetTextColor(int color) 函数修改 TextView 的文本颜色为红色 编译 运行程序, 最终界面如图 -1 所示.2.2 Button 和 ImageButton Button( 按钮 ) 是普通按钮控件, 用于处理人机交互事件 用户单击该控件, 第 章
Android 程序设计 8 能触发相应的响应事件 如果需要在按钮上显示图像, 则可以使用 ImageButton ( 图像按钮 ) Button 继承了 TextView 的所有方法和属性, 而 ImageButton 继承自 ImageView 设置 ImageButton 的图像时, 需要提前将图像文件放置在 res/drawable 目录下, 然后在 xml 文件中设置 ImageButton 的 android.src 属性 此外, 还可以在 Java 代码中调用 ImageButton 的 setimagesource(int id) 方法设置图像 图 -1 TextView 样式 注册 Button 响应事件的常用方式是实现 OnClickListener 接口 单击按钮时, 通过该监听接口触发 OnClick() 方法, 可以实现特定功能 Button 调用 OnClickListener 接口可用如下方法 : 按钮对象.setOnClickListener(onClickListener listener) 参数 listener 可以传入直接的 OnClickListener 对象, 也可以在 Activity 实现 OnClickListener 后, 直接传入 this 例 -2 演示 Button 和 ImageButton 控件的使用方法 打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 ButtonDemo 打开 activity_main.xml, 分别添加一个 Button 控件和一个 ImageButton 控件, 此外再添加一个 TextView, 以便显示按钮单击事件的结果 具体代码如下 : 1 2 4 5 6 7 8 <?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:layout_width="wrap_content"
9 10 11 12 1 14 15 16 17 18 19 20 21 android:text="button" android:id="@+id/button" /> <ImageButton android:layout_width="wrap_content" android:id="@+id/imagebutton" android:src="@mipmap/ic_launcher" /> <TextView android:layout_width="wrap_content" android:id="@+id/textview" /> </LinearLayout> 第 7~11 行声明了一个 ID 为 button 的 Button 控件 第 12~18 行声明了一个 ID 为 ImageButton 的控件, 第 16 行表明该 ImageButton 的图像为 mipmap 下的 ic_launcher 图像 ( 此为 Android Studio 默认的应用图标 ), 如果是应用自定义图像, 则该语句为 android:src="@drawable/*** ",*** 为文件名, 不带后缀 打开 MainActivity.class 文件, 引用两个按钮控件, 实现并注册单击事件监听器 OnClickListener 修改如下: 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 package com.example.buttondemo; import ; public class MainActivity extends AppCompatActivity implements View. OnClickListener { ImageButton imagebutton; TextView textview; Button button; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); imagebutton = (ImageButton)findViewById(R.id.imageButton); textview = (TextView)findViewById(R.id.textView); button = (Button)findViewById(R.id.button); imagebutton.setonclicklistener(this); button.setonclicklistener(this); 第 章
Android 程序设计 40 17 18 19 20 21 22 2 24 25 } } @Override public void onclick(view v) { if(v==imagebutton) textview.settext("imagebutton 被点击 "); else if(v==button) textview.settext("button 被点击 "); } 其中第 15 16 行分别注册了 imagebutton 和 button 的单击事件监听器 第 19 行到第 2 行实现了接口 View.OnClickListener 的 OnClick() 函数, 从而实现了该接口 单击 button 后, 运行结果如图 -2(a) 所示, 单击 imagebutton 后运行结果如图 -2(b) 所示 (a) (b) 图 -2 Button 和 ImageButton 样式.2. EditText EditText( 文本编辑框 ) 是用来输入和编辑字符的控件 EditText 继承自 TextView, 是一个特殊的具有编辑功能的 TextView 控件, 所以 TextView 的方法和 xml 文件元素属性都适用于 EditText, 如图 - 所示 EditText 的主要 xml 文件元素属性有 : android.editable 是否可编辑, 取值为 true 或 false android.inputtype 输入字符类型, 取值主要有 text( 文本 ) TextPassword ( 密码 ) number( 数字 ) phone( 手机号码 ) 等, 可以用 连接多个取
值 此外输入类型也可以单独由 android.numeric android.password android. phonenumber 等属性设置 图 - EditText 的继承关系 android.hint 文本编辑框的提示语 更上一层 EditText 对象.getText() 返回的是 Editable 类型, 用于字符串处理时, 需调用它的 tostring() 函数, 即 EditText 对象.getText().toString() 例 - 演示 EditText 控件的使用方法打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 EditTextDemo 打开 activity_main.xml, 分别添加输入类型为 text( 默认 ) password 的用户名 EditText 和密码 EditText, 再添加一个 Button 作为登录按钮, 和一个 TextView 提示登录结果信息 1 2 4 5 6 7 8 9 10 11 12 1 14 15 <?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"> <EditText android:layout_width="match_parent" android:id="@+id/edittext1" android:hint=" 用户名 "/> <EditText android:layout_width="match_parent" android:inputtype="textpassword" 第 章
Android 程序设计 42 16 17 18 19 20 21 22 2 24 25 26 27 android:id="@+id/edittext2" android:hint=" 密码 "/> android:layout_width="wrap_content" android:text=" 登录 " android:id="@+id/button" /> <TextView android:layout_width="wrap_content" android:id="@+id/textview" /> </LinearLayout> 其中用户名 EditText 的输入类型是默认的 Text( 文本 ), 而第 15 行设置密码 EditText 的输入类型是 TextPassword( 密码 ), 在输入的时候, 只会显示对应个数的 * 修改 MainActivity.java 文件, 实现登录按钮的 OnClickListener 接口, 设置为当用户名 EditText 输入为 android 且密码 EditText 输入为 12 时, 显示登录成功, 否则显示登录失败 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 17 package com.example.edittextdemo; import ; public class MainActivity extends AppCompatActivity { EditText usernameedit,passwdedit; Button loginbutton; TextView textview; @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); usernameedit = (EditText)findViewById(R.id.editText1); passwdedit = (EditText)findViewById(R.id.editText2); loginbutton = (Button)findViewById(R.id.button); textview = (TextView)findViewById(R.id.textView); loginbutton.setonclicklistener(new View.OnClickListener() { @Override public void onclick(view v) {
18 19 20 21 22 2 24 25 26 if(usernameedit.gettext().tostring().equals("android")&& passwdedit.gettext().tostring().equals("12")) textview.settext(" 登录成功 "); else textview.settext(" 登录失败 "); } }); } } 此类中实现 Button 的单击事件没有采用 Activity 实现 OnClickListener 接口的方法, 而是直接在第 15 行注册监听器传参数时新建一个 OnClickListener 对象, 这种方法也是可行的, 但在 Button 较多时, 代码会显得比较臃肿 运行结果如图 -4 所示 图 -4 EditText 样式. Layout 组件 Layout 组件是布局组件, 其中可以嵌套容纳其他组件, 又称为容器 (container) Layout 组件规定了子组件的摆放规则, 因此开发者通过 Layout 组件在 xml 布局文件中控制组件的位置 间距 排列及对齐方式等, 从而设计出更具结构化 更为美观, 同时兼容多种分辨率的界面 Layout 组件的共同父类是 ViewGroup 正常情况下,xml 布局文件的根节点是一个 layout 组件, 该组件必须有命名空间 :xmlns:android="http://schemas.android.com/apk/res/android" 开发者可以根 第 章
Android 程序设计 44 据需求在该节点下嵌套添加其他组件作为子节点, 以丰富界面 开发者可以设置 Layout 组件的 android:gravity 属性, 控制子组件在组件中的位置 或者设置 android:layout_gravity 属性控制组件自身在父组件中的位置 这两个属性的值可以为 top( 上 ) bottom( 下 ) left( 左 ) right( 右 ) center_horizontal ( 水平居中 ) center_vertical( 垂直居中 ) 常用的 layout 组件有 FrameLayout( 框架布局 ) LinearLayout( 线性布局 ) RelativeLayout( 相对布局 ) TableLayout( 表格布局 ) GridLayout( 网格布局 )..1 FrameLayout FrameLayout( 框架布局 ) 是所有布局中最为简单的一种, 也叫帧布局 该布局直接在屏幕上开辟出了一块空白区域, 当向其中添加组件的时候, 默认情况下, 所有的组件都会放置于这块区域的左上角 开发者可以为子组件添加 layout_gravity 属性, 从而指定组件的对齐方式 如果有多个子元素, 那么后加的子元素就会覆盖先加的子元素 例 -4 演示 FrameLayout 的用法打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 FrameLayout 按默认方式先后添加两个 TextView, 分别命名为 第一层 和 第二层, 再添加名为 第三层 的 TextView, 并设置其位置为 FrameLayout 的中央 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 <?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"> <TextView android:layout_width="200dp" android:layout_height="200dp" android:text=" 第一层 " android:textsize="50sp" android:background="#e9521" android:gravity="center"/> <TextView gravity 属性控制 View 中子内容的分布位置 android:layout_width="90dp" android:layout_height="90dp" android:text=" 第二层 " android:textsize="0sp"
17 18 19 20 21 22 2 24 25 26 27 28 29 android:background="#d9e18" android:gravity="center"/> <TextView android:id="@+id/textview" android:layout_width="200dp" android:layout_height="200dp" android:textsize="50sp" android:text=" 第三层 " android:layout_gravity="center" android:background="#18f50d" android:gravity="center" /> </FrameLayout> 第 5~11 行声明了一个 200dp 200dp 的背景为 #e9521( 十六进制颜色 ) 文本为 第一层 的 TextView 第 12~18 行声明了一个 90dp 90dp 的背景为 #d9e18 文本为 第二层 的 TextView 后生成的子元素会覆盖先生成的子元素, 因此 第二层 会覆盖 第一层 第 19~28 行生成一个 200dp 200dp 的背景为 #18f50d 文本为 第三层 的 TextView, 并通过设置其属性 android:layout_gravity 为 center, 以达到将其放置在 FrameLayout 中央的效果 最后的运行界面如图 -5 所示 图 -5 FrameLayout..2 LinearLayout LinearLayout ( 线性布局 ) 是一般开发中最常用的布局组件之一 在 第 章
Android 程序设计 46 LinearLayout 中, 所有的子元素都在水平或垂直方向依次排列 若为垂直方向, 则每行只有一个子元素 ; 若为水平方向, 则每列只有一个子元素, 如图 -6 所示 默认情况下,LinearLayout 的排列方向为水平 开发者可以设置 android:orientation 属性控制方向, 取值可以为 horizontal( 水平 ) 或 vertical( 垂直 ) (a) 水平方向排列 图 -6 LinearLayout 水平和垂直样式 (b) 垂直方向排列 如果开发者想令子组件按比例分配, 可以将子组件对应方向的长度设为 0, 即水平分布时令 android:layout_width="0dp", 垂直分布时令 android:layout_height= "0dp", 然后设置 android.layout_weight 的值 最后组件所占比例为该组件 layout_weight 值除以该组件父组件的所有子元素的 layout_weight 之和 例 -5 演示如何令 LinearLayout 组件中的子组件按比例分布打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 LinearLayout 打开 activity_main.xml 文件, 在根节点 LinearLayout 下分别添加用户名 EditText 密码 EditText 和登录 Button, 令其在水平方向按 2:2:1 的比例分布 1 2 4 5 6 7 8 9 10 11 12 1 14 <?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="horizontal"> <EditText android:layout_width="0dp" android:layout_weight="2" android:hint=" 用户名 "/> <EditText android:layout_width="0dp"
15 16 17 18 19 20 21 22 2 24 25 android:layout_weight="2" android:inputtype="textpassword" android:id="@+id/edittext2" android:hint=" 密码 "/> android:layout_width="0dp" android:layout_weight="1" android:text=" 登录 " android:id="@+id/button" /> </LinearLayout> 第 6 行设置 LinearLayout 子组件的排列方式为水平 第 10 15 22 行分别设置所在组件的 layout_weight 为 2 2 和 1, 所以这三个组件最后所占比例分别为 2/(2+2+1)=40% 40% 和 20% 应用程序界面如图 -7 所示 图 -7 LinearLayout 样式.. RelativeLayout RelativeLayout( 相对布局 ) 是一种非常灵活的布局控件, 采用相对其他组件的位置的布局方式 RelativeLayout 中通常使用相对父组件的位置或通过 id 关联其他组件, 以达到上 下 左 右对齐的目的 为达到灵活的目的, 相对布局有很多属性, 如表 -2 所示 表 -2 相对布局的属性 属性取值说明 android:centerinparent true false 是否在父控件的中央 android:centerinhorizontal true false 水平方向上是否在父控件的中央 android:centerinvertical true false 垂直方向上是否在父控件的中央 第 章
Android 程序设计 续表 属性取值说明 48 android:layout_alignparenttop true false 是否与父组件顶部对齐 android:layout_alignparentbottom true false 是否与父组件底部对齐 android:layout_alignparentleft true false 是否与父组件左端对齐 android:layout_alignparentright true false 是否与父组件右端对齐 android:layout_aligntop @id/*** 与 id 为 *** 的控件顶部平齐 android:layout_alignbottom @id/*** 与 id 为 *** 的控件底部平齐 android:layout_alignleft @id/*** 与 id 为 *** 的控件左端平齐 android:layout_alignright @id/*** 与 id 为 *** 的控件右端平齐 android:layout_above @id/*** 底部和 id 为 *** 的控件顶部平齐 android:layout_below @id/*** 顶部和 id 为 *** 的控件底部平齐 android:layout_toleftof @id/*** 右端和 id 为 *** 的控件左端平齐 android:layout_torightof @id/*** 左端和 id 为 *** 的控件右端平齐 例 -6 演示 RelativeLayout 的用法打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 RelativeLayout 添加一个 TextView, 使其居中, 再添加四个 TextView, 分别分布在其四个角上 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 17 <?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:layout_width="wrap_content" android:text=" 中央 " android:id="@+id/textview" android:layout_centerinparent="true" android:textsize="50sp" /> <TextView android:layout_width="wrap_content" android:textsize="50sp" android:text=" 左上 "
18 19 20 21 22 2 24 25 26 27 28 29 0 1 2 4 5 6 7 8 9 40 41 42 4 android:layout_above="@+id/textview" android:layout_toleftof="@+id/textview" /> <TextView android:layout_width="wrap_content" android:textsize="50sp" android:text=" 右上 " android:layout_above="@+id/textview" android:layout_torightof="@+id/textview" /> <TextView android:layout_width="wrap_content" android:textsize="50sp" android:text=" 左下 " android:id="@+id/textview4" android:layout_below="@+id/textview" android:layout_toleftof="@+id/textview" /> <TextView android:layout_width="wrap_content" android:textsize="50sp" android:text=" 右下 " android:layout_below="@+id/textview" android:layout_torightof="@+id/textview" /> </RelativeLayout> 其中, 第 6~12 行声明了一个 id 为 textview 的 TextView 控件, 第 11 行将其放置在父组件 RelativeLayout 的中央 第 1~42 行分别声明了 4 个 TextView 控件, 并分别通过 android:layout_above 和 android:toleftof android:above 和 android:torightof android:layout_below 和 android:toleftof android:layout_below 和 android:torightof 的组合放置到 id 为 textview 的组件的左上 右上 左下 右 下角 最终程序运行界面如图 -8 所示 第 章
Android 程序设计 50 图 -8 RelativeLayout 样式..4 TableLayout TableLayout( 表格布局 ) 是将布局页面划分为行和列构成的单元格, 继而将子元素放置在单元格中的一种布局 该布局组件中用 <TableRow> 和 </TableRow> 标记表示一行单元格 与大多数编程语言相似,TableRow 的行数和列数都是从 0 开始计数 此外,Table 中子元素可以不指定 android:layout_height 和 android:layout_width, 因为它们默认为单个单元格的高和宽 TableLayout 的主要全局属性如下 : android:collapsecolumns 隐藏 TableLayout 里面指定的列 若有多列需要隐藏, 可用逗号将需要隐藏的列序号隔开 若需要隐藏所有单元格, 则将其设置为 * ; android:stretchcolumns 设置指定的列为可伸展的列, 以填满该行中剩下的空白空间 若有多列, 则需要设置为可伸展, 可用逗号将需要伸展的列序号隔开 android:shrinkcolumns 设置指定的列为可收缩的列 当可收缩的列太宽时, 此列会自动收缩, 以免被挤出屏幕 当需要设置多列为可收缩时, 可
用逗号隔开需要收缩的列序号 子元素即单元格的属性如下所示 android:layout_column 指定该控件在 TableRow 中占据的列 android:layout_span 指定该控件所跨越的列数 例 -7 演示 TableLayout 的主要用法打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 TableLayout 打开 activity_main.xml 文件, 按下列代码添加一个 4 行 列的 TableLayout 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 17 18 19 20 21 22 2 24 25 26 27 28 29 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:shrinkcolumns="2"> android:text=" 单独占据一行 "/> <TableRow> android:text="1 行 0 列 "/> android:text="1 行 1 列 " /> </TableRow> <TableRow> android:text="2 行 0 列 "/> android:text="2 行 1 列 "/> android:text="...2 行 2 列..."/> </TableRow> <TableRow> android:text=" 行 0 列 "/> android:text=" 行 2 列 " android:layout_column="2" /> </TableRow> </TableLayout> 第 章
Android 程序设计 52 第 5 6 行声明的 Button 并没有放置在任何一个 TableRow 中, 因此它会被当作单独的一行, 故完全占据了第 0 行 第 7~12 行 TableRow 标签表示这是完整的一行, 其中声明的两个 Button 自动按照前后顺序排列, 成为第 1 行第 0 列和第 1 行第 1 列 同样, 第 1~20 行再次声明一行, 即第 2 行 原本第 2 行第 2 列的 Button 空间会由于过大显示到屏幕外, 但第 4 行设置了 android:shrinkcolumns="2", 即第 2 列会自动收缩适配屏幕大小, 所以第 2 行第 2 列的 Button 最终完整显示出来了 第 21~28 行又声明一行, 即第 行 此行中的第 2 个 Button 原本应该放置在第 1 列, 但是第 26 行 android:layout_column="2" 设置了其占据第 2 列, 故其最终位置为第 行第 2 列 程序的最终运行界面如图 -9 所示 图 -9 TableLayout 样式..5 GridLayout GridLayout( 网格布局 ) 是 Android 4.0 以上版本新增加的一种布局, 与 TableLayout 大同小异, 同样将布局划分为行 列和单元格, 并同样支持调整容器中组件的对齐方式 但相比 TableLayout,GridLayout 更为灵活, 支持同时控制水平和垂直方向的空间对齐方式, 并且支持控件跨行分布 和 TableLayout 一样, GridLayout 对行和列的计数也是从 0 开始的 如果没有指定行数和列数, 控件会被默认放在上个控件右边的单元格, 若此行已满, 则会放在下一行的第 1 个单元格 GridLayout 的主要全局属性有 :
android:rowcount 设置行数 android:columncount 设置列数 子元素属性主要有 : android:layout_gravity 设置控件的对齐方式 android:layout_row 设置控件所在行数 android:layout_column 设置控件所在列数 android:layout_rowspan 设置控件横跨的行数 android:layout_columnspan 设置空间横跨的列数 例 -8 演示 GridLayout 的主要用法打开 Android Studio, 新建一个带空白 Activity 的项目, 命名为 GridLayout 打开 activity_main.xml 文件, 声明一个 行 列的 GridLayout 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 17 18 19 20 21 22 2 24 <?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:rowcount="" android:columncount=""> android:text="1" android:layout_gravity="fill" android:layout_rowspan="2" android:layout_columnweight="1"/> android:text="2" android:layout_gravity="fill" android:layout_columnspan="2" android:layout_columnweight="1"/> android:text="" android:layout_gravity="fill" android:layout_columnspan="2" android:layout_column="0" android:layout_columnweight="1"/> android:text="4" 第 章
Android 程序设计 54 25 26 27 28 29 0 1 2 4 5 android:layout_gravity="fill" android:layout_row="1" android:layout_rowspan="2" android:layout_column="2" android:layout_columnweight="1"/> android:text="5" android:layout_row="1" android:layout_columnweight="1" android:layout_column="1"/> </GridLayout> 其中第 5 行声明 GridLayout 的行数为, 第 6 行声明列数为 第 7~11 行, 声明了一个 Button 控件 没有指定行和列的时候, 控件默认按从左到右 从上到下排列, 所以该 Button 在第 0 行第 0 列 第 10 行设置 android:layout_rowspan="2", 即其横跨两行, 所以其最终会占据第 0 1 行第 1 列 android:layout_columnweight 是为了设置列的宽度比例, 此处所有 Button 控件的该属性都设为相同的值 1, 所以最后单列的宽度相等 其余 Button 控件的设置方法都与第一个相似, 此处不再赘述 最终程序运行的界面如图 -10 所示 图 -10 GridTable 样式..6 Layout 布局小结 除上述详细介绍的常用布局之外, 有时可能还会用到其他布局, 比如 AbsoluteLayout( 绝对布局 ) 通过指定组件的 x y 坐标控制组件的位置 在
实际开发中, 倘若只用一种布局, 往往难以做出美观的界面 因此多数情况下, 界面会有多种布局嵌套使用, 以达到复杂精巧的预期效果 相同布局可以嵌套, 不同布局也可以相互嵌套, 非常灵活.4 复合按钮 Android 系统本身封装了多种按钮, 除了默认的 Button, 常用的还有 Checkbox RadioButton 和 ToggleButton 三种复合按钮 这三种特殊按钮都继承自类 CompoundButton, 而 CompoundButton 类又继承自 Button 类.4.1 CheckBox CheckBox 有选中与未选中两种状态, 默认是未选中状态, 其一般形式如图 -11 所示 其最重要的属性是 Checked, 在代码中可以用 ischeck() 方法判断 改变该属性的方式有三种 1.XML 中声明 android:checked="false" 或者 android:checked="true" 2. 代码动态改变 对象. setchecked(false) 或者 对象.setChecked(true) 或者 对象.toggle(). 用户触摸 Checked 属性的改变会触发 OnCheckedChange 事件, 因此可以注册 OnCheckedChangeListener 监听器来监听此事件 第 章
Android 程序设计 56 图 -11 CheckBox.4.2 RadioButton RadioButton 为单选按钮, 一般样式如图 -12 所示 通常需要与 RadioGroup 一同使用 RadioGroup 是可以容纳多个 RadioButton 的容器 每个 RadioGroup 中的 RadioButton 同时只能有一个被选中 不同的 RadioGroup 中的 RadioButton 互不相干, 即如果组 A 中有一个被选中了, 组 B 中依然可以有一个被选中 大部分场合下, 一个 RadioGroup 中至少有两个 RadioButton 大部分场合下, 一个 RadioGroup 中的 RadioButton 默认会有一个被选中, 并建议将其放在 RadioGroup 中的起始位置 Checked 属性也是 RadioButton 最重要的属性, 与 checkbox 相同, 它也可以用三种方式改变 check 属性 而且当 checked 属性改变时, 也会触发 OnCheckedChange 事件, 因此也可以注册 OnCheckedChangeListener 监听器来监听此事件 图 -12 RadioButton.4. ToggleButton ToggleButton 允许用户在两种状态之间切换一个设置, 比如灯的 开 和 关, 其基本样式如图 -1 所示 Android 4.0(API level 14) 及以上版本还引入了一种全新的复合按钮 Switch, 它的功能与 ToggleButton 相同, 但样式发生了变化, 其样式如图 -14 所示 图 -1 ToggleButton 图 -14 Switch
与 CheckBox 和 RadioButton 相同,ToggleButton 也是 CompoundButton 的子类 Checked 属性也是其最重要的属性 也可以用三种方式改变 check 属性 而且当 checked 属性改变时, 也会触发 OnCheckedChange 事件, 因此也可以注册 OnCheckedChangeListener 监听器来监听此事件 习题 1. 请编程实现 TextView 类的一个子类, 使得它默认指定某些特性, 比如文字大小 颜色和样式 2. 请编程实现 View 类的一个子类, 使得它具有某些样式 ( 可能需要用到 Android 绘图功能 ). 请实现一个简易加法计算器, 它应该有两个输入和一个输出 请注意界面的美观 4. 请实现一个计算器, 它应该有 0~9 十个数字 小数点和加减乘除以及等于 清空 删除一个字符等按钮 5. 请实现一个学生信息录入系统, 它应该可以输入姓名 学号 联系方式和选择性别, 以及确认是否团员 请注意界面的美观 第 章