行动装置提供各种不同应用的程式,让使用者可以随时执行一些工作、浏览网页和玩一些游戏。因为萤幕尺寸的关系,它不会像一般个人电脑上的应用程式,需要设计一些很复杂的操作画面。透过触控萤幕的操作,行动装置应用程式提供简单与直觉的操作画面,通常不需要使用说明书,就可以让使用者顺利的使用应用程式。
Android是一个开放的作业系统,这表示所有厂商都可以设计与制造各种使用Android作业系统的行动装置,这些装置的萤幕尺寸和内建的设备,并不是固定的。尤其是萤幕的尺寸和分辨率,会让Android应用程式的画面设计,跟其它技术比较不一样。一个设计良好的应用程式,在萤幕是3.4吋、分辨率是480X800的装置上执行,还有在萤幕是4.7吋、分辨率是1920X1080的装置上执行,应用程式的画面看起来应该是一样的。
Android应用程式的画面设计,采取一种比较灵活的方式,作法也跟其它技术比较不一样。这一章说明设计应用程式画面的重要概念与方式,学习使用各种Android画面控件和版面配置元件。
## 5-1 设计使用者界面
一般的Android应用程式,通常需要提供一些画面,让使用者执行操作或浏览资料。应用程式的画面是使用一些Android API中的画面物件组合起来的,这些画面API主要在“android.widget”套件下,这个套件提供各种画面元件的类别,例如在应用程式画面上的一个按钮,就是一个“Button”类别的物件。认识基本的画面元件以后,在规划与设计应用程式的画面时,你就可以制作像这样的文件资料:
[![AndroidTutorial5_02_02_01](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_01-300x195.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_01.png)
在上面的规划资料里面,你可以决定使用哪些画面元件,例如用来显示文字的“TextView”元件,或是让使用者输入文字用的“EditText”元件。针对整个画面的安排,你也会决定控制元件排列方式的画面配置元件,例如这个画面适合使用“RelativeLayout”这种画面配置元件。像按钮或输入这类元件,需要在程式码中设计按钮的工作与读取输入的内容,所以需要为它们取一个名称,这个工作也可以在规划应用程式的画面时就决定好元件的名称,在设计画面与撰写程式的时候,会使用这些名称执行一些设定。
跟一般其它技术的画面元件类似,Android跟画面相关的元件在“android.view”和“android.widget”两个套件中。下图显示主要的套件和部份的元件类别:
[![AndroidTutorial5_02_02_02](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_02-300x157.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_02.png)
上面的类别图形只有显示少数几个元件,在android.view套件下的“View”类别,是所有画面元件的父类别。同样在这个套件下的“ViewGroup”是所有画面配置元件的父类别。它们各自有很多子类别,提供各种画面和配置元件。大部份的Android应用程式设计,应该使用XML格式的画面配置档为Activity元件设计画面,它放在“res\layout”目录下,这是在这里说明的主要设计方式。
## 5-2 画面元件的基本设定
Android的画面元件是View和ViewGroup的子类别,提供各种应用程式画面需要的元件。在画面配置档中设计应用程式的画面,是采用与这些与元件类别名称一样的标签,再依照需要加入一些设定,所以跟程式设计的作法很不一样。画面配置档一定要放在“res/layout”目录,档案名称必须是小写的字母和底线,副档名一定是“.xml”。一个基本的画面配置档内容会像这样:
~~~
<?xml version="1.0" encoding="utf-8"?>
<!-- 使用Button标签,设定整个画面只有一个按钮元件 -->
<!--
xmlns:android="..." 这个设定一定要加在第一个标签,
后面还有其它标签的话,就不用再加入这个设定
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello! GUI!" />
~~~
这个画面配置档只有在画面中加入一个按钮元件,它使用的是“Button”标签,在API里面也有一个名称为“Button”的类别。设计好需要的画面配置档,就可以在Activity元件的onCreate方法中,呼叫“setContentView”指定元件使用指定的画面资源:
~~~
public class TestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设定画面配置资源
// 指定的参数在“R.layout.”后面是档案名称
setContentView(R.layout.activity_test);
}
}
~~~
不管是设计一个简单或复杂的画面,对放到画面中的元件,都有一些基本而且通用的设定,在大部份的情况下,一定要为画面元件加入下列决定大小的设定:
* android:layout_width:设定画面元件的宽度
* android:layout_height:设定画面元件的高度
因为各种Android装置的萤幕尺寸与分辨率并不是一样的,所以在设定画面元件的大小时,应该要设定为“match_parent”或“wrap_content”。例如把元件的宽度设定为match_parent时,这个画面元件的宽度就会占满所用的空间。设定为wrape_content的话,会根据这个画面元件自动调整为足够显示内容的空间。如果画面中只有一个按钮元件,不同的设定组合会有不同的效果:
[![AndroidTutorial5_02_02_03](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_03-300x118.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_03.png)
这样的设定方式,让应用程式的画面在不同尺寸与分辨率的萤幕显示的时候,看起来会是一样的。你也可以为画面元件指定固定的宽与高,在设定的时候使用这些单位,例如“android:layout_width= "120sp"”:
* px:萤幕画素。
* dp:每英吋画面,160dp为一英吋。
* sp:和dp一样,不过会根据装置设定的字号自动调整。
* in:英吋。
* mm:公厘。
决定画面元件的大小以后,你可能需要设定与其它元件的间隔距离,这个设定在画面有比较多元件的时候,可以让所有元件不会黏成一团,画面看起来会好一些。这些是用来执行与其它元件的间隔距离设定,使用上面说明的单位设定需要的间隔:
* android:marginTop:设定上方的间隔。
* android:marginBottom:设定下方的间隔。
* android:marginLeft:设定左侧的间隔。
* android:marginRight:设定右侧的间隔。
* android:margin:设定上、下、左、右为同样的间隔。
你还可以控制画面元件内容的间隔距离设定,让一个元件的内容与它使用的空间有一点间隔,元件本身看起来就不会那么拥挤。这些是用来执行元件内容间隔距离的设定:
* android:paddingTop:设定内容上方的间隔。
* android:paddingBottom:设定内容下方的间隔。
* android:paddingLeft:设定内容左侧的间隔。
* android:paddingRight:设定内容右侧的间隔。
* android:padding:设定内容上、下、左、右为同样的间隔。
画面元件还有一个可以控制内容位置的设定,设定名称是“android:gravity”,可以让你比较容易把内容设定为需要的位置。下面是它的设定值:
* top、bottom、left、right:设定画面元件的内容对齐上、下、左、右。
* center_vertical、center_horizontal:设定画面元件的内容对齐垂直或水平的中央。
* center:设定画面元件的内容对齐垂直与水平的中央。
* fill_vertical、fill_horizontal:设定画面元件的内容占满垂直或水平空间。
* fill:设定画面元件的内容占满垂直与水平空间。
这些设定值也可以使用组合的方式,例如希望把内容对齐下方的右侧,就可以设定为“bottom|right”,多个设定值之间使用“|”隔开。这是一个设定效果的范例,它使用一个占满整个画面的TextView元件,如果没有设定的话,默认的内容位置是在左上方,使用一些不同的设定控制内容的位置:
[![AndroidTutorial5_02_02_04](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_04-300x114.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_04.png)
如果是可以显示文字内容的画面元件,例如文字(TextView)、按钮(Button)或输入(EditText)元件,可以为它们加入文字内容与样式设定:
* android:text:设定画面元件的文字内容。
* android:textSize:设定文字的大小。
* android:textAppearance:使用系统的默认值设定文字的大小,设定的格式为“?android:attr/设定值”,有textAppearanceLarge(大)、textAppearanceMedium(中)和textAppearanceSmall(小)三种设定值。
* android:textColor:设定文字的颜色。
* android:background:设定背景颜色。
## 5-3 使用画面配置元件
就算是一个简单的Android应用程式,大部份都会在一个画面中使用多个画面元件,组合成应用程式需要的画面,一个画面只有一个画面元件的情况应该是不多的。所以你在规划与设计应用程式的画面时,除了知道要使用哪一些画面元件,也要规划好画面使用配置方式,就是决定所有需要的元件如何在画面上排列。
因为各种Android实体装置的萤幕尺寸与分辨率并不是一样的,所以画面元件的排列、位置与大小也应该不是固定的,应用程式在不同装置运作的时候,画面看起来才会一样。所以Android建议你应该使用“Layout”来设计画面元件的排列方式,Layout是ViewGroup的子类别,ViewGroup是一种容器元件,可以把其它元件放在这些元件里面,组合成需要的画面。
在规划与设计应用程式画面的时候,应该就可以决定它们该使用哪一种Layout。Android在“android.widget”套件中提供的“LinearLayout”和“RelativeLayout”是基本的Layout元件。LinearLayout可以设定为依照水平(horizontal)或垂直(vertical)排列。RelativeLayout使用画面元件相对的位置来排列,适合用在比较不规则的画面元件配置。画面元件放在这两种Layout中的效果会像这样:
[![AndroidTutorial5_02_02_05](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_05-300x136.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_05.png)
如果应用程式的画面比较复杂一些,这样的Layout应该就不够用了,所以使用这些Layout的时候,可以使用巢状的方式组合成一个复杂的排列。例如这个画面的排列方式,在最外层使用垂直排列的LinearLayout,里面又包含上下两个LinearLayout,它们也可以依照自己的需求,设定为垂直和水平排列:
[![AndroidTutorial5_02_02_06](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_06-300x162.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_06.png)
ViewGroup还提供一种很常使用的“TableLayout”,它可以把画面切割为表格,你可以依照画面的需求设定为像是2X4的区块,每一个区块都可以放一个画面元件,如果需要的画面不是一个固定的表格,也可以调整它们的区块。使用TableLayout排列的画面会像这样:
[![AndroidTutorial5_02_02_07](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_07-300x104.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_07.png)
### 5-3-1 LinearLayout
LinearLayout可以提供比较简单的画面配置,你可以设定它依照水平(由左到右)或垂直(由上往下)排列画面元件。如果需要使用这种排列方式,在画面配置档中加入LinearLayout标签,使用“android:orientation”设定排列的方式,“horizontal”为水平,“vertical”为垂直:
~~~
<?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或horizontal" >
// 放在这里的画面元件会依照指定的方式排列
</LinearLayout>
~~~
放在LinearLayout里面的元件,还可以设定它们占用的空间比例,这样就可以让这种看起来很单纯的排列方式,变得比较灵活一些。要设定元件占用的空间比例,使用“android:layout_weight="比例"”,依照LinearLayout设定为水平或垂直排列,设定元件的比例后,它的宽或高就由比例来决定,所以应该把元件的宽或高设定为“0dp”。如果其中有一个元件没有设定比例,它会依照自己宽与高的设定决定大小,其它空间再由比例决定各自的大小。搭配使用这些设定,就可以很灵活的设定各种画面的配置:
[![AndroidTutorial5_02_02_08](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_08-300x110.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_08.png)
### 5-3-2 RelativeLayout
应用程式需要的画面,可能不会都是很规则的排列,如果画面元件的位置与排列比较复杂与不规则的时候,就比较适合使用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" >
// 使用关联的方式排列画面元件
</RelativeLayout>
~~~
放在RelativeLayout标签中的画面元件,可以依照画面的需求,决定自己在画面中的位置,也可以设定自己与其它元件的相对位置。这些是在RelativeLayout标签中的画面元件可以使用的设定:
* android:layout_位置="@id/元件名称":决定自己在指定元件的相对位置,格式中的“位置”可以使用above、below、toLeftOf或toRightOf,依照顺序表示把自己放在指定元件的上方、下方、左边或右边。
* android:layout_align对齐="@id/元件名称":决定自己和指定元件的对齐方式,格式中的“对齐”可以使用Top、Bottom、Left或right,依照顺序表示把自己的上、下、左或右对齐指定的元件。
* android:layout_alignParent对齐="true|flase":决定自己与容器的对齐方式,格式中的“对齐”可以使用Top、Bottom、Left或right,设定为true的时候,依照顺序表示把自己对齐容器的上、下、左或右。
* android:layout_center对齐="true|flase":决定自己与容器对齐中央的方式,格式中的“对齐”可以使用Horizontal、Vertical或InParent,设定为true的时候,依序表示将自己对齐容器的水平中央、垂直中央或容器中央。
搭配使用这些RelativeLayout提供的设定,就算是比较复杂或不规则的画面,也可以很容易完成设计的工作:
~~~
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout … >
<TextView
android:id="@+id/account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ACCOUNT: "
android:textSize="24sp" />
<!-- 把自己放在account元件的右边 -->
<EditText
android:id="@+id/account_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/account"
android:paddingLeft="6sp" />
<!-- 把自己放在account_value元件的下方,而且对齐容器右边 -->
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/account_value"
android:text="OK" />
<!-- 把自己放在ok元件的左边,而且上方也对齐它 -->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/ok"
android:layout_toLeftOf="@id/ok"
android:text="Cancel" />
</RelativeLayout>
~~~
这个画面配置档呈现的画面会像这样:
[![AndroidTutorial5_02_02_09](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_09-242x300.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_09.png)
### 5-3-3 TableLayout
ViewGroup还提供一种很常使用的“TableLayout”画面排列方式,它可以把画面切割为表格,你可以依照画面的需求,把画面切割为像是2X4的区块,每一个区块都可以放一个画面元件,如果需要的画面不是一个固定的表格,也可以调整它们的区块。这种画面配置使用“TableLayout”标签,搭配“TableRow”标签建立需要的表格。TableLayout会控制画面元件的宽与高,所以在这个标签中的画面元件都不需要设定宽与高,就算加入设定也不会有效果:
~~~
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- 第一列 -->
<!-- TableRow不需要设定宽与高 -->
<TableRow>
<!-- 所有的元件都不需要设定宽与高 -->
...
</TableRow>
<!-- 第二列 -->
<TableRow>
...
</TableRow>
</TableLayout>
~~~
TableLayout会管理与控制画面元件的大小,默认的情况,画面元件的宽度都是“wrap_content”的效果。你可以在TableLayout标签中加入这些设定,执行元件的宽度与是否隐藏的设定:
* android:stretchColumns:放大指定的字段宽度。第一个字段是0,可以设定多个字段,例如“1,3,5”;设定为“*”表示所有字段。
* android:shrinkColumns:宽度不够显示所有内容的时候,指定的字段会自动缩小。第一个字段是0,可以设定多个字段,例如“1,3,5”;设定为“*”表示所有字段。
* android:collapseColumns:隐藏指定的字段。第一个字段是0,可以设定多个字段,例如“1,3,5”;设定为“*”表示所有字段。
在TableLayout中加入android:stretchColumns的设定,可以让指定的字段占用较大的空间。
[![AndroidTutorial5_02_02_10](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_10-300x126.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_10.png)
### 5-3-4 结合多种画面排列元件
上面说的LinearLayout、RelativeLayout和TableLayout,单独使用的时候,在设计一些比较复杂的画面时,就比较不符合需求。不过只要是Layout元件都可以搭配使用,所以在规画与设计应用程式的画面时,如果想要设计一个比较复杂的画面,应该要把画面上所有的元件切割成适合的区块,为每一个区块挑选一个合适的排列方式,最后再把它们结合起来。例如像这个计算机应用程式的画面,就会依照它们的需求使用LinearLayout和TableLayout组合成这样的画面:
[![AndroidTutorial5_02_02_11](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_11-300x203.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_11.png)
## 5-4 建立记事本应用程式主画面
了解Android应用程式画面的设计方式后,现在要回到记事本应用程式,为它设计一个用来显示所有资料的主画面:
[![AndroidTutorial5_02_02_12](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_12-300x217.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_12.png)
这个画面的需求并不会太复杂,使用LinearLayout画面配置元件就可以了,安排画面元件的时候,最好帮它们设定边界,元件才不会挤在一起。开启“res/values/dimens.xml”,加入需要的尺寸资源:
~~~
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="default_padding">6dp</dimen>
<dimen name="title_txt_size">24sp</dimen>
<!-- 加入边界尺寸资源设定 -->
<dimen name="default_margin">2dp</dimen>
</resources>
~~~
接下来开启“res/layout/activity_main.xml”档案,把它改为下面的内容:
~~~
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/item_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="@dimen/default_margin"
android:dividerHeight="1sp"
android:background="@drawable/retangle_drawable"
android:divider="@color/divider_color" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="@dimen/default_margin"
android:padding="@dimen/default_padding"
android:background="@drawable/retangle_drawable"
android:text="@string/app_name"/>
</LinearLayout>
~~~
执行这个应用程式,看看它在模拟装置中显示的画面。这个画面中的ListView是用来显示资料列表的元件,目前还没有为它设定任何资料,所以看起来是空白的。指定资料的工作必须在Activity元件的程式码执行,所以在画面配置档为ListView元件使用“android:id”为它设定一个名称。开启专案的“MainActivity.java”,修改为下面的内容:
~~~
package net.macdidi.at2;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 为ListView元件设定三笔资料
String[] data = {
"关于Android Tutorial的事情",
"一只非常可爱的小狗狗!",
"一首非常好听的音乐!"};
int layoutId = android.R.layout.simple_list_item_1;
ArrayAdapter adapter =
new ArrayAdapter(this, layoutId, data);
ListView item_list = (ListView) findViewById(R.id.item_list);
item_list.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
~~~
执行这个应用程式,检查ListView元件是否显示三笔资料:
[![AndroidTutorial5_02_02_13](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_13-167x300.png)](http://www.codedata.com.tw/wp-content/uploads/2015/02/AndroidTutorial5_02_02_13.png)
- 第一堂
- 第一堂(1)西游记里的那只猴子
- 第一堂(2)准备 Android Studio 开发环境
- 第一堂(3)开始设计 Android 应用程式
- 第一堂(4)开发 Android 应用程式的准备工作
- 第二堂
- 第二堂(1)规划与建立应用程式需要的资源
- 第二堂(2)设计应用程式使用者界面
- 第二堂(3)应用程式与使用者的互动
- 第二堂(4)建立与使用 Activity 元件
- 第三堂
- 第三堂(1)为ListView元件建立自定画面
- 第三堂(2)储存与读取应用程式资讯
- 第三堂(3)Android 内建的 SQLite 数据库
- 第四堂
- 第四堂(1)使用照相机与麦克风
- 第四堂(2)设计地图应用程式 - Google Maps Android API v2
- 第四堂(3)读取装置目前的位置 - Google Services Location
- 第五堂
- 第五堂(1)建立广播接收元件 - BroadcastReceiver
- 第五堂(2)系统通知服务 - Notification
- 第五堂(3)设计小工具元件 - AppWidget
- 第六堂
- 第六堂(1)Material Design - Theme与Transition
- 第六堂(2)Material Design - RecylerView
- 第六堂(3)Material Design - Shared Element与自定动画效果