ViewGroup 主要作為 AdapterView 與 Layout 的 parent class,就是一種 View 的 container,剩下的 Android UI 元件都是繼承自 View class。
開發 Android UI 可以單獨用 coding 的方式,也可以用 XML 設定的方式,或者兩種方法混著用,用 XML 定義 UI,然後用 coding 加上互動。
使用 coding 方式建立 UI:
public class LayoutMgr extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout main = new LinearLayout(this); main.setOrientation(LinearLayout.VERTICAL); Button newBtn = new Button(this); newBtn.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); newBtn.setText("新遊戲"); main.addView(newBtn); Button confBtn = new Button(this); confBtn.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); confBtn.setText("設定"); main.addView(confBtn); this.setContentView(main); } }
使用 XML 設定方式建立 UI 的部份,請參考 Android Layout Managers - LinearLayout,要補充的是,讓 Android 知道是使用 XML 設定。
public class LayoutMgr extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.main); } }特別的地方是 this.setContentView(R.layout.main) 裡的 R.layout.main,這是 Android 自動產生的 class,Android 會將 res 目錄下的 XML 設定檔產生 class 檔到 gen 目錄下,供 coding reference 使用。
最後一種建立 UI 的方式,也是最常見的方式,就是使用 XML 建立頁面,然後使用 coding 加上互動的行為,XML 部份請參考 Android Layout Managers - LinearLayout。
public class LayoutMgr extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.findViewById(R.id.startBtn).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { // TODO - start a new game } }); this.findViewById(R.id.endBtn).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { // TODO - exit the game } }); } }這邊要強調的是使用 this.findViewById(...) 來取得 XML 裡定義的元件,另外也可以在 coding 裡改變 UI 的外觀或設定。
TextView
像是 HTML 裡的 lable,除了純粹文字輸出,Android 另外強化了自動連結的功能。
<TextView android:id="@+id/tv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:autoLink="all" android:text="..." />加上 autoLink 屬性之後,Android 會自動解析內容,適當地加上連結,autoLink 支援的連結種類有 web(網址)、phone(電話號碼)、email、map(地址)以及 all,預設為 none。
也可以使用 coding 的方式設定,參考 Linkify。
EditText
像是 HTML 裡的 text input + textarea,預設為 text input,在編輯狀態按下 enter 就會多一行變成 textarea,可以加上 singelLine 屬性強制為 text input。
有很多像是自動檢查拼字的 autoText、自動轉大寫的capitalize、只接受數字的 digits、或密碼專用的 password 等屬性可以使用,請參考 TextView Attributes(因為 EditText 繼承自 TextView)。
EditText 允許一點點的 style,只接受 <i/>、<b/>、<u/>,要從 XML 輸入 style,只能用 reference 的方式,如果直接在 XML 輸入 style,可是會看到驚奇的。
<EditText android:id="@+id/et" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="<i>aaa<i/><b>bbb<b/><u>ccc<u/>" />
只能用 reference 的方式輸入 style。
<EditText android:id="@+id/et" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/style" />res/values/strings.xml
<resources> <string name="style"><i>iii</i> <b>bbb</b> <u>uuu</u></string> </resources>正確的 style:
AutoCompleteTextView
從自訂的字串集中產生自動完成功能,XML 設定如下:
<AutoCompleteTextView android:id="@+id/actv" android:layout_width="fill_parent" android:layout_height="wrap_content"/>特別的地方在 coding 部份:
public class UI extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String[] phoneList = new String[] { "0910123456", "0920123456", "0921123456", "0935123456", "0938123456" }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, phoneList); ((AutoCompleteTextView) this.findViewById(R.id.actv)).setAdapter(adapter); } }先建立字串集,再建立 adapter,最後將 adpater 傳給 AutoCompleteTextView 元件。
這邊有一個特別的地方,就是 adapter 的 UI 來源,上面用的是 Android 內建的範本(android.R.layout.simple_dropdown_item_1line),還有很多範本可用,也可以自訂專屬的範本,只要在 res/layout 目錄下建立 XML 設定檔,例如 list_item.xml。
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="6dp" android:textSize="12sp" android:textColor="#000"> </TextView>這樣就可以使用 R.layout.list_item 得到一個緊實的下拉清單。
最後一個重點是,自動完成的功能得輸入兩個字元才會驅動,只輸入一個字元是沒有反應的。
MultiAutoCompleteTextView
怪怪版的 AutoCompleteTextView,可以在一個 EditText 使用多次自動完成,只要輸入指定的字元後,就可以重新使用自動完成。
從前一個 AutoCompleteTextView 範例做修改,只要將 AutoCompleteTextView 改成 MultiAutoCompleteTextView,然後在 coding 裡,呼叫 mactv.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer()) 就可以了。
Button
在 XML 建立一個 Button,然後在 coding 裡加上互動行為。
public class Dialog extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ((Button) this.findViewById(R.id.dialogA)).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // do something } }); } }但是這樣會有一個小小地效能問題,就是使用匿名 inner class 會消耗一些記憶體,當 Button 用的愈多,inner class 愈多,效能就愈慢。
可以在使用最少 class 的前提下,將主 activity 實做 OnClickListener,再用 switch 判斷不同的 Button,就可以避免因為 inner class 造成記憶體過載的情況。
public class Dialog extends Activity implements OnClickListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ((Button) this.findViewById(R.id.dialogA)).setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.dialogA: this.startActivity(new Intent(this, DialogA.class)); break; } } }ImageButton
影像按鈕。
<ImageButton android:id="@+id/imgBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/appengine_lowres"/> <ImageButton android:id="@+id/imgBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ae_gwt_java"/>
特別的地方在於讀取影像的方式,只要將影像檔放置於 drawable 目錄下即可,支援 png、jpg與 gif 三種格式,不用另外在 XML 中定義,即可以在 XML 或 coding 中用檔名(不包括副檔名)reference。
ToggleButton
雙態按鈕。
<ToggleButton android:id="@+id/tglBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="錄音中" android:textOff="開始錄音"/>
CheckBox
同 HTML 的 checkbox。
<CheckBox android:id="@+id/oneBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="One"/> <CheckBox android:id="@+id/twoBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Two"/> <CheckBox android:id="@+id/threeBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Three"/>
常用的 method 有 isChecked()、setChecked(...)、toggle() 與 setOnCheckedChangeListener(...)。
RadioGroup & RadioButton
同 HMLT 的 radio。
<RadioGroup android:id="@+id/rdoBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <RadioButton android:id="@+id/oneBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="One"/> <RadioButton android:id="@+id/twoBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Two"/> <RadioButton android:id="@+id/threeBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Three"/> </RadioGroup>
RadioGroup 裡可以放置 RadioButton 以外的 View 元件,而 RadioGroup 的單選限制僅作用於 RadioGroup 裡的 RadioButton 子元件,所以 RadioGroup 裡的非 RadioButton 子元件或者 RadioGroup 外的 RadioButton 元件不會影響 RadioGroup 的單選限制。
一旦任一個 RadioButton 元件被點選之後,就無法從頁面上回復到所有未點選的初始狀態,只能透過呼叫 clearCheck() 來回復到所有未點選的初始狀態。
DatePicker & TimePicker
<DatePicker android:id="@+id/datePicker" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TimePicker android:id="@+id/timePicker" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
沒有留言:
張貼留言