制作一個簡單的用戶界面
這節課里面,我們來開發一個XML布局文件,這個布局文件里面會包含一個text field,文本輸入框,和一個按鈕button。下一節課里面,會教大家怎么在按下一個按鈕的時候,跳轉到另一個Activity。
這里先簡單解釋一下Android界面的構成。AndroidApp的界面是使用View和ViewGroup構建起來的。View通常就是我們常見的UI小部件,比如按鈕Button、文本控件TextView等;而ViewGroup是一個View的容器,它可以限制這個容器里面的View是怎么排列的,比如GridView就是網格類型的排序方式,ListView就是一個從上往下順序排列的列表。
Android里面,在開發界面的時候,可以使用XML文件來定義界面UI以及UI的層次結構等等。
Android里面的布局其實都是屬於某一類ViewGroup而已,那么這節課里面,我們會用到線性布局LinearLayout。
一個圖片說明下View和ViewGroup的關系
新建一個布局文件
1.Android Studio里面, 在res/layout文件夾下, 打開activity_main.xml文件。
一開始創建項目的時候,BlankActivity模版會自動創建這個xml布局文件,這里會自動生成一個RelativeLayout相對布局,並且里面有一個TextView文本控件,顯示一行文字,“HelloWorld!”
2.在預覽面板里面,就是上圖右邊Preview部分,點擊預覽面板右上角的這個按鈕,可以隱藏預覽。
在Android Studio里面,當你打開一個布局文件的時候,會第一時間顯示預覽界面,這就是所謂的WYSIWYG(所見即所得)。點擊這個預覽里面的某一個元素的時候,編輯面板中會自動定位到對應的代碼位置。這節課里面,我們主要是直接操作XML代碼來開發我們的布局文件。
3.刪除TextView元素
4.把RelativeLayout改成LinearLayout元素
5.給LinearLayout元素添加一個屬性,android:orientation,並設為"horizontal"。
6.刪除LinearLayout的padding和tools:context屬性
最后修改成這樣:res/layout/activity_main.xml
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="horizontal" > 6 </LinearLayout>
LinearLayout是一個橫向或者豎向順序排列view元素的一個布局,可以通過android:orientation這個屬性來設置橫豎的方向。每一個子元素都會按照順序來一個接着一個的顯示在這個布局里面。
其他兩個屬性,android:layoutwidth和android:layoutheight,分別代表了這個布局的寬和高。
由於這個LinearLayout在這個界面上面是一個根視圖的布局,所以一般我們會把款和高設置成"match_parent"。這個值表示盡可能的擴大當前這個布局,讓他填滿他的父布局。當然這里這個LinearLayout已經是根視圖的布局了,所以這里就直接鋪滿整個屏幕了。
更多關於布局屬性的信息,可以參考這里。
添加一個文本輸入框
添加文本輸入框EditText的時候,你必須得設置一些特定的屬性。
1.activity_main.xml文件中, <LinearLayout>元素里面, 定義一個<EditText>元素,然后設置一個id屬性,值為@+id/edit_message。
2.設置layout_width和layout_height屬性,值為wrap_content。
3.設置hint屬性,值為一個string對象,名字是edit_message。
代碼參考如下:
1 <EditText android:id="@+id/edit_message" 2 android:layout_width="wrap_content" 3 android:layout_height="wrap_content" 4 android:hint="@string/edit_message" />
我們一起看一下,文本輸入框EditText共添加了如下幾個屬性:
這個屬性,給這個元素指定了一個特定的id,在當前這個布局文件里面,這個id應該是唯一的。設置了這個id以后,我們就可以在代碼里很方便的找到這個元素,引用這個元素,並進行一些操作等。(這個會在下一節課里面看到具體用法)。
當你需要在XML文件中引用任何對象的時候,就需要用到@符號。一般緊跟@符號后面,是資源類型,然后是斜杠“/”,然后是資源名字,比如上面那個“edit_message”。
在資源類型前面的“+”,只有在你需要定義一個全新的資源ID的時候,才需要寫上去。當你編譯app的時候,SDK工具會識別這些新加的資源ID,把他們創建到一一對應的R.java(gen/R.java)文件中。 當這樣定義了這個ID以后,別的地方引用這個資源ID的時候,就不需要再加“+”了。所以,只有在全新定義一個ID的時候才需要用到這個“+”,引用別的資源的時候,比如string,layout等等,都不需要在寫上這個“+”了。
android:layout_width
和 android:layout_height
“wrap_content”的意思是,這個view元素的大小,跟他的內容所需要的大小一致,會實時根據需求調整大小。如果這里設置了"match_parent",那這個EditText就會直接填滿整個屏幕了,因為這個值表示塞滿整個父布局LinearLayout。
這個值表示,文本輸入框為空的時候,要顯示一些什么提示性的文字。可以看到這里並沒有直接在這個hint后面跟一個字符串,比如“這里輸入姓名”這樣的硬編碼,而是"@string/edit_message",代表了引用了一個資源文件里面定義的string值。谷歌會推薦這種引用資源的寫法,更加靈活,而且如果養成習慣的話,在一些復雜的工程里面,會在一定的程度上提高代碼的質量。這里引用完以后,會有一個錯誤。先別急,后面慢慢解決。
這里會發現hint這里引用的資源名稱和我們定義的這個EditText的id是一樣的,但是沒有沖突,為什么呢。這里其實是因為資源類型不同,上面定義的是id,后面這個是一個string。當資源類型不同時,命名相同就沒有關系了。
添加String資源
一般情況下,你的Android項目的資源文件夾下有這樣一個專門存放字符串的資源文件res/value/strings.xml。在這里添加一個名為“edit_message”的新字符串,將值設置為“輸入信息”。
1.AndroidStudio里面,找到res/values目錄,打開strings.xml。
2.添加一行,string名稱為"edit_message",值為"輸入信息"。
3.添加一行,string名稱為"button_send",值為"發送"。下一步我們會做一個按鈕,所以這里提前添加一下按鈕上的文字。
4.刪掉“hello world”這個字符串。
最后,strings.xml應該是這樣的:
1 <resources> 2 <string name="app_name">My Application</string> 3 4 <string name="edit_message">Enter a message</string> 5 <string name="button_send">Send</string> 6 <string name="action_settings">Settings</string> 7 </resources>
對於用戶界面中的文本,盡量都使用string資源。當你用資源來處理的時候,你可以單獨只修改這個資源的內容,就可以改變所有引用了這個資源的地方了,這會使得這個app在未來有很好的可維護性。而且,這種把字符串外部化的操作方式,還有益於app的本地化開發,即自動兼容多套語言。關於本地化開發的更多內容,可以參考這里。
添加按鈕
1.在Android Studio中,選擇res/layout目錄,編輯activity_main.xml文件。
2.在LinearLayout元素中,定義一個Button元素,把他放在EditText元素后面。
3.設置這個按鈕的寬和高屬性都是"wrap_content",這樣的話,按鈕的大小就會根據設置在按鈕上的文字大小自動調整。
4.定義按鈕的android:text屬性,值為在上面你定義過的“button_send”這個string資源。
現在這個LinearLayout應該是這樣:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="horizontal" > 6 <EditText android:id="@+id/edit_message" 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:hint="@string/edit_message" /> 10 <Button 11 android:layout_width="wrap_content" 12 android:layout_height="wrap_content" 13 android:text="@string/button_send" /> 14 </LinearLayout>
提示: 這里按鈕上面沒有設置id屬性,是因為在代碼中我們暫時不會用到它
在預覽里面可以看到,輸入框和按鈕,都根據自身內容大小,調整到了一定的大小。
上面看起來,按鈕應該是正常了,但是這個輸入框的寬度,當用戶輸入的內容越來越多的時候,我們這樣設置真的合適嗎?其實更好的設置應該是讓輸入框的寬度把除了按鈕以外的所有橫向空間全部占掉,把按鈕擠到最右邊去。這里就教你一個線性布局里面常用的屬性,android:layout_weight
。
weight是一個簡單的數字,他代表了這個view在當前線性布局里面的橫向或者縱向占比(視LinearLayout的方向而定)。這有點像在飲料配方,比如“2份蘇打水,1份糖漿”,意味着三分之二的飲料是蘇打水,三分之一是糖漿。舉個例子,比如有兩個view,第一個view設置weight是2,第二個設置成1,那么總共weight有3,第一個view就會占據2/3,第二個只占1/3,這時候,如果在添加一個view進來,設置weight是1,那么第一個就占1/2,后面兩個都占1/4,因為此時weight總量變成4了。
而這里,只有一個設置了weight,意味着這個view可以盡可能的拉伸自己,占完所有的空余部分。
使輸入框占滿屏幕
為了使EditText能占滿剩余的全部空間,需要這樣做:
1.在activity_main.xml文件中,給EditText添加屬性layout_weight值為1。
2.然后,修改EditText的layout_width屬性值為0dp。
此時,res/layout/activity_main.xml文件應該為:
<EditText android:id="@+id/edit_message" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="@string/edit_message" />
當你設置了weight的時候,最后把寬度設置成0dp,而不是其他值。因為如果你設置了比如“wrap_content”的時候,系統會根據設置的參數去計算一遍對應這個值的view寬度,而又由於設置了weight,這里計算出來的寬度是無效的,必須根據weight值重新計算一遍,這就導致了性能上的浪費。
設置好以后,預覽圖如下:
此時,整個布局文件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="horizontal" > <EditText android:id="@+id/edit_message" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="@string/edit_message" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" /> </LinearLayout>
運行App
- 1.AndroidStudio中,直接點擊運行按鈕。
- 2.命令行模式下
ant debug
adb install bin/MyFirstApp-debug.apk
下一節講怎么點擊按鈕,把文本框里的內容傳到另一個界面去。