- Android Studio開發實戰:從零基礎到App上線 (移動開發叢書)
- 歐陽燊
- 2706字
- 2020-11-28 17:31:42
3.6 實戰項目:登錄App
現在是實戰項目時間,大家如此費力地看書學習,還不就是為了在實際項目中派上用場。凡是賺錢的App,都要掌握用戶資源,這便少不了為用戶提供登錄頁面。下面設計并實現App的登錄功能。
3.6.1 設計思路
如今樓市瘋狂上漲,要買房自然少不了房貸,根據不同的貸款方式與還款方式計算出的月供數額各不相同。如果手機上有房貸計算器,就會便利許多。房貸計算器絕對是一個方便實用的App,本書迄今為止介紹的App開發知識足夠寫一個房貸計算器App了,如圖3-26所示。本章學到的主要控件基本都能派上用場,包括RelativeLayout、EditText、RadioButton、CheckBox、Spinner等。讀者若有興趣可自行編碼練習,補充房貸計算的具體業務邏輯。

圖3-26 房貸計算器的效果圖
本章的實戰項目最終選定App登錄頁面,是因為要復習Activity的相關概念與用法。Activity是Android中最常用的組件,后續章節全部都會用到,所以要好好加以鞏固。
各家App的登錄頁面大同小異,要么是用戶名與密碼組合登錄,要么是手機號與驗證碼組合登錄,如果要做得更好一點,就要提供忘記密碼與記住密碼等功能。我們的App登錄項目把這些功能綜合一下,都呈現到頁面上,因為是練手,所以盡量讓學到的控件都派上用場。登錄頁面的設計圖初稿如圖3-27所示。

圖3-27 登錄頁面的效果圖
讀者找找看這個效果圖包含哪些本章的新控件?一定會發現以下6個控件。
● 單選按鈕RadioButton:用來區分是密碼登錄還是驗證碼登錄。
● 下拉框Spinner:用于區分用戶類型是個人用戶還是公司用戶。
● 編輯框EditText:用來輸入手機號碼和密碼。
● 復選框CheckBox:用于判斷是否記住密碼。
● 相對布局RelativeLayout:指定手機號碼的編輯框放在手機號碼TextView的右邊。這里使用線性布局LinearLayout也可以。
● 框架布局FrameLayout:忘記密碼的按鈕與密碼輸入框疊加。
至此,本章介紹的新控件基本都派上用場了。另外,本項目還要演示活動頁面的的跳轉功能,點擊“忘記密碼”按鈕跳轉到找回密碼頁面,找回密碼頁面的效果如圖3-28所示。

圖3-28 找回密碼頁面的效果圖
找回密碼的頁面挺簡單,主要問題是兩個頁面之間的跳轉有哪些注意事項?頁面跳轉肯定要傳遞參數,一般唯一標識的手機號碼要傳過去,不然下一個頁面不知道要為哪個手機號碼修改密碼;新密碼也要傳回去,不然上一個頁面不知道密碼被改成什么了。
另外,有一個細微的用戶體驗問題:用戶會去找回密碼,肯定是發現輸入的密碼不對。修改完密碼回到登錄頁面時,密碼輸入框里還是原來錯誤的密碼,此時用戶清空錯誤密碼才能輸入新密碼。我們的App想讓用戶覺得好用,就得急用戶之所急、想用戶之所想,像之前錯誤密碼的情況應當由App在返回登錄頁面時自動清空原來錯誤的密碼。自動清空的操作放在onActivityResult方法中處理是一個辦法,但這樣處理有一個問題,如果用戶直接按返回鍵回到登錄頁面,onActivityResult方法發現數據為空就不會處理。
這個問題其實不難,只要認真看書,結合前面關于Activity生命周期的說明,就能夠找到解決辦法。重寫onRestart方法(確保是返回頁面),在方法內部加上清空密碼框的處理即可。這樣一來,無論用戶是修改完密碼回到登錄頁,還是點擊返回鍵回到登錄頁,App都會自動清空密碼框。
3.6.2 小知識:提醒對話框AlertDialog
使用驗證碼登錄時,App要向用戶手機發送短信驗證碼,但發送短信需要服務器支持,所以這里暫時使用隨機數模擬驗證碼,然后以對話框的形式在界面上提示用戶。另外,在登錄的過程中,App時常需要彈窗提示用戶選擇“是”或“否”,以此判斷下一步的處理邏輯。在本實戰項目開始之前,建議讀者先演練一下提醒對話框(AlertDialog)的用法。
AlertDialog是Android中最常用的對話框,可以完成常見的交互操作,如提示、確認、選擇等功能。AlertDialog沒有公開的構造函數,必須借助AlertDialog.Builder才能完成參數設置,AlertDialog.Builder的常用方法如下。
● setIcon:設置標題的圖標。
● setTitle:設置標題的文本。
● setMessage:設置內容的文本。
● setPositiveButton:設置肯定按鈕的信息,包括按鈕文本和點擊監聽器。
● setNegativeButton:設置否定按鈕的信息,包括按鈕文本和點擊監聽器。
● setNeutralButton:設置中性按鈕的信息,包括按鈕文本和點擊監聽器,該方法比較少用。
通過AlertDialog.Builder設置完參數,還需調用create方法才能生成AlertDialog對象。最后調用AlertDialog對象的show方法,在頁面上彈出提醒對話框。
下面是個提醒對話框的代碼:
public void onClick(View v) { if (v.getId() == R.id.btn_alert) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("尊敬的用戶"); builder.setMessage("你真的要卸載我嗎?"); builder.setPositiveButton("殘忍卸載", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { tv_alert.setText("雖然依依不舍,但是只能離開了"); } }); builder.setNegativeButton("我再想想", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { tv_alert.setText("讓我再陪你三百六十五個日夜"); } }); AlertDialog alert = builder.create(); alert.show(); } }
提醒對話框的彈窗效果如圖3-29所示,該對話框有標題、有內容,還有兩個按鈕。

圖3-29 AlertDialog的效果圖
用戶點擊不同的按鈕會觸發不同的處理邏輯。圖3-30所示為點擊“我再想想”按鈕后的頁面,圖3-31所示為點擊“殘忍卸載”按鈕后的頁面。

圖3-30 點擊“我再想想”的截圖

圖3-31 點擊“殘忍卸載”的截圖
3.6.3 代碼示例
前面的設計不但給出了兩個頁面的效果圖,而且給出了業務邏輯的大概思路,接下來主要是編碼將其實現。編碼過程分為3個步驟:
步驟01 先想好代碼文件與布局文件的名稱,比如登錄頁面的代碼文件取名LoginMainActivity.java,布局文件取名activity_login.xml;找回密碼頁面的代碼文件取名LoginForgetActivity.java,布局文件取名activity_login_forget.xml。記得在AndroidManifest.xml中注冊兩個頁面的acitivity節點,注冊代碼如下:
<activity android:name=".LoginMainActivity" /> <activity android:name=".LoginForgetActivity" />
步驟02 在res/layout目錄下創建布局文件activity_login.xml和activity_login_forget.xml,根據頁面效果圖編寫兩個頁面的布局定義文件。
步驟03 在項目的包名目錄下創建類LoginMainActivity和LoginForgetActivity,填入具體的控件操作與業務邏輯代碼。
下面是登錄頁面LoginMainActivity.java的主要代碼片段:
public void onClick(View v) { String phone = et_phone.getText().toString(); if (v.getId() == R.id.btn_forget) { if (phone==null || phone.length()<11) { Toast.makeText(this, "請輸入正確的手機號", Toast.LENGTH_SHORT).show(); return; } if (rb_password.isChecked() == true) { Intent intent = new Intent(this, LoginForgetActivity.class); intent.putExtra("phone", phone); startActivityForResult(intent, mRequestCode); } else if (rb_verifycode.isChecked() == true) { mVerifyCode = String.format("%06d", (int)(Math.random()*1000000%1000000)); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("請記住驗證碼"); builder.setMessage("手機號"+phone+",本次驗證碼是"+mVerifyCode+",請輸入驗證碼"); builder.setPositiveButton("好的", null); AlertDialog alert = builder.create(); alert.show(); } } else if (v.getId() == R.id.btn_login) { if (phone==null || phone.length()<11) { Toast.makeText(this, "請輸入正確的手機號", Toast.LENGTH_SHORT).show(); return; } if (rb_password.isChecked() == true) { if (et_password.getText().toString().equals(mPassword) ! = true) { Toast.makeText(this, "請輸入正確的密碼", Toast.LENGTH_SHORT).show(); return; } else { loginSuccess(); } } else if (rb_verifycode.isChecked() == true) { if (et_password.getText().toString().equals(mVerifyCode) ! = true) { Toast.makeText(this, "請輸入正確的驗證碼", Toast.LENGTH_SHORT).show(); return; } else { loginSuccess(); } } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == mRequestCode && data! =null) { //用戶密碼已改為新密碼 mPassword = data.getStringExtra("new_password"); } } //從修改密碼頁面返回登錄頁面,要清空密碼的輸入框 @Override protected void onRestart() { et_password.setText(""); super. onRestart(); } private void loginSuccess() { String desc = String.format("您的手機號碼是%s,類型是%s。恭喜你通過登錄驗證,點擊“確 定”按鈕返回上個頁面", et_phone.getText().toString(), typeArray[mType]); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("登錄成功"); builder.setMessage(desc); builder.setPositiveButton("確定返回", new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which){ finish(); } }); builder.setNegativeButton("我再看看", null); AlertDialog alert=builder.create(); alert.show(); }
下面是找回密碼頁面LoginForgetActivity.java的代碼:
public class LoginForgetActivity extends AppCompatActivity implements OnClickListener { private EditText et_password_first; private EditText et_password_second; private EditText et_verifycode; private String mVerifyCode; private String mPhone; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login_forget); et_password_first = (EditText) findViewById(R.id.et_password_first); et_password_second = (EditText) findViewById(R.id.et_password_second); et_verifycode = (EditText) findViewById(R.id.et_verifycode); findViewById(R.id.btn_verifycode).setOnClickListener(this); findViewById(R.id.btn_confirm).setOnClickListener(this); mPhone = getIntent().getStringExtra("phone"); } @Override public void onClick(View v) { if (v.getId() == R.id.btn_verifycode) { if (mPhone==null || mPhone.length()<11) { Toast.makeText(this, "請輸入正確的手機號", Toast.LENGTH_SHORT).show(); return; } mVerifyCode = String.format("%06d", (int) (Math.random() * 1000000 % 1000000)); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("請記住驗證碼"); builder.setMessage("手機號"+mPhone+",本次驗證碼是"+mVerifyCode+",請輸入驗證碼"); builder.setPositiveButton("好的", null); AlertDialog alert = builder.create(); alert.show(); } else if (v.getId() == R.id.btn_confirm) { String password_first = et_password_first.getText().toString(); String password_second = et_password_second.getText().toString(); if (password_first==null || password_first.length()<6 || password_second==null || password_second.length()<6) { Toast.makeText(this, "請輸入正確的新密碼", Toast.LENGTH_SHORT).show(); return; } else if (password_first.equals(password_second) ! = true) { Toast.makeText(this, "兩次輸入的新密碼不一致", Toast.LENGTH_SHORT).show(); return; } else if (et_verifycode.getText().toString().equals(mVerifyCode) ! = true) { Toast.makeText(this, "請輸入正確的驗證碼", Toast.LENGTH_SHORT).show(); return; } else { Toast.makeText(this, "密碼修改成功", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(); intent.putExtra("new_password", password_first); setResult(Activity.RESULT_OK, intent); finish(); } } } }
- Leap Motion Development Essentials
- PostgreSQL 11從入門到精通(視頻教學版)
- 微信公眾平臺開發:從零基礎到ThinkPHP5高性能框架實踐
- EPLAN實戰設計
- C語言程序設計學習指導與習題解答
- Reactive Android Programming
- RSpec Essentials
- NetBeans IDE 8 Cookbook
- Clojure for Java Developers
- Mockito Essentials
- Clojure Polymorphism
- 人人都能開發RPA機器人:UiPath從入門到實戰
- Learning D3.js 5 Mapping(Second Edition)
- SaaS攻略:入門、實戰與進階
- Building Microservices with .NET Core 2.0(Second Edition)