接着上一講留下的“需求”:
設計一個登陸界面:
允許用戶輸入用戶名,密碼;
用戶點擊“Login”之后,如果用戶名為admin, 密碼為123則顯示“登陸成功”;
如果用戶名密碼其中之一不正確,紅色字體顯示“登陸失敗!”
首先我們來建立一個新的項目:
圖標那一步就隨便選吧,下一步:
這一步與上次有點不同, 這次我們不要ADT 幫我們創建任何的Activity,我們只需要一個空的項目。
點擊Finish后,我們會發現,項目文件視圖下, 與上次的不一樣,src, res/layout 是空的,這一會需要我們自己去添加了。
首先來明確一下我們現在的目標:
建立一個包含登錄框的界面,並將它顯示在我們的手機(模擬器)上。
建立一個界面的主要步驟是什么呢?主要有以下幾步:
- 在res/layout下創建布局文件;
- 在src下創建Activity子類,並將布局文件與這個Activity聯系起來。
- 在AndroidManifest.xml程序配置文件中,添加Activity的聲明。
我們先來
1. 創建布局文件:
在Eclipse項目文件中選中layout 文件夾,在工具欄里點擊下面圖標
在彈出的窗口,填上這個xml布局文件的文件名,Root Element 根節點就選擇Linearlayout即可
點擊下一步,這一步是選擇更多配置屬性的,暫且不用理會,直接點擊Finish。
我們發現,在res/layout 下面多了一個login.xml文件,同時Android 的Layout 編輯器也把它打開了。
切換到“source”代碼視圖,今天我們不用“所見即所得”的傻瓜拖拽方式。
我們看到xml代碼是這樣的:
<?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" > </LinearLayout>
根節點是LinearLayout,即線性布局,所謂線性布局,有點像J2SE上的流式布局,就是其中的UI元素,會按水平或者垂直方向順序地鋪開。
LinearLayout有個xml屬性:android:orientation,它有兩個可選值:vertical和horizontal,指明該線性布局中的元素,是以垂直(vertical)還是水平(horizontal)方向排列。
下面是兩種方式的示意圖:
接下來,我們要添加兩個輸入框,讓用戶輸入用戶名,密碼。
輸入框使用的是EditText, 我們在LinearLayout中添加兩個EditText
<?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:id="@+id/login_username" android:layout_width="300dp" android:layout_height="wrap_content" android:hint="Type name here...." android:text="" > </EditText> <EditText android:id="@+id/login_password" android:layout_width="300dp" android:layout_height="wrap_content" android:hint="Type password here...." android:inputType="textPassword" android:text="" > </EditText> </LinearLayout>
對比每個節點屬性,我們發現,不管是LinearLayout還是EditText,都會至少包含
android:layout_width
android:layout_height
上一講我們有介紹這兩個屬性,這里再詳細介紹一下,
不管是android:layout_width還是android:layout_height 都有四種可選填的值:
- wrap_content
- fill_parent
- match_parent
- 具體數值
前面三個參考上一講。
具體數值可以填像素px,如300px, 也可以填dp. dp(也寫作dip)是Android平台上特有的長度計量單位,它是與設備屏幕無關的單位,強烈建議我們在設計界面元素時,都使用dp,而非px! 原因這里不多拓展,以后會詳細描述。
還有一個重要的屬性是:android:id, 它是UI元素的唯一標識,格式為@+id/XXXXXXX
保存之后,我們會發現,在gen文件夾下面, ADT為我們自動生成了代碼R.java:
他們都是靜態且final 的類或者成員。它的作用是,為資源建立索引,以便代碼中或者layout中方便的引用。
public final class R { public static final class attr { } public static final class drawable { public static final int ic_launcher=0x7f020000; } public static final class id { public static final int login_password=0x7f060001; public static final int login_username=0x7f060000; } public static final class layout { public static final int login=0x7f030000; } public static final class string { public static final int app_name=0x7f040000; } public static final class style { public static final int AppTheme=0x7f050000; } }
接下來我們再添加一個用於提交的按鈕,以及用於顯示結果的文本:
<Button android:id="@+id/login_submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登錄"/> <TextView android:id="@+id/login_result" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="用於顯示登錄的結果"/>
android:hint是用於提示文本,當android:text有值是,會被替換。
切換回“所見即所得”的圖形編輯視圖預覽一下:
布局文件創建完成,我們進行第二步:
2. 編寫代碼
在src右鍵New->Class->
需要注意的是,該LoginActivity類必須繼承自Activity類
public class LoginActivity extends Activity { /** * 必須重載父類的onCreate */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.login);//將布局文件與代碼關聯起來 //獲取布局文件中的UI元素對象 final EditText mUserName = (EditText) this.findViewById(R.id.login_username); final EditText mPassword = (EditText) this.findViewById(R.id.login_password); Button mSubmit = (Button)this.findViewById(R.id.login_submit); final TextView mResult = (TextView)this.findViewById(R.id.login_result); //設置按鈕點擊之后的事件處理 mSubmit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String userName = mUserName.getText().toString(); String password = mPassword.getText().toString(); if("admin".equals(userName) && "123".equals(password)){ mResult.setText("恭喜您,登錄成功!"); }else{ mResult.setText("登錄失敗,用戶名或密碼不正確!"); } } }); } }
注意以下幾點:
- 必須重載onCreate()方法,而且必須首先調用一次父類的方法super.onCreate(savedInstanceState);
- setContentView()方法用於關聯布局文件,應該在onCreate中先調用,后面才能獲取到UI元素的對象。
- 因為要供OnClickListener匿名內部類調用,所以局部變量要聲明為final.
- EditText.getText()方法返回的是Editable對象,而不是String,需要調用toString();
3. AndroidManifest.xml聲明activity
所有的Activity定義好了之后,只有在AndroidManifest.xml中聲明過,才會有效。
在application節點中添加:
<activity android:name="LoginActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
android:name對應的是代碼中Activity的類名,因為前面有程序默認包聲明“package="com.stanley.basiclogin"”,所以可以省略包名直接寫類名,或者寫錯.類名。如果Activity類所在的包不是默認包,則需要添加包名作為前綴。所以這個例子中 LoginActivity 或者.LoginActivity都是正確的。
保存,編譯完成之后,我們就可以開始運行代碼了。
以下是運行結果:
我們再來回顧一下,建立新界面的步驟:
- 在res/layout下創建布局文件;
- 在src下創建Activity子類,並將布局文件與這個Activity聯系起來。
- 在AndroidManifest.xml程序配置文件的application節點中,添加Activity的聲明。如果需要程序運行就啟動該Activity,要加main 的Inten Filter.
下一講, 我們來探討一下各種布局管理器。