三三要成為安卓糕手
零:布局轉換
在很多工程當中用的都是LinearLayout和relativelayout,這兩者都可以轉化為Constrainlayout
注:這種用法并不能精確轉換,具體還是要根據自己的需求來做布局約束
一:snackbar顯示彈窗
((20250705191320-a3dyocx “之前學習過Toast彈窗,類比思想snackbar;我們以之前設計過的登錄頁面為基礎展開彈窗的學習”))
1:代碼
private EditText etUserName;private EditText etPassword;private String userName;private String password;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_relative_converse_constraint_layout);//1:獲取用戶名框view 和 密碼框viewetUserName = findViewById(R.id.et_user_name);etPassword = findViewById(R.id.et_password);//2:定位到登錄按鈕Button button = findViewById(R.id.btn_login);//3:對按鈕進行監聽button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//3.1:獲取框里輸入的內容userName = etUserName.getText().toString().trim();password = etPassword.getText().toString().trim();//3.2 如果用戶名為空 就彈窗if(userName.length() == 0){Snackbar.make(button,"用戶名為空",Snackbar.LENGTH_LONG).show();return;}//3.3 如果密碼為空 也彈窗if(password.length() == 0){Snackbar.make(button,"密碼為空",Snackbar.LENGTH_LONG)//4.2.1 并且彈出輸入法.setAction("去輸入密碼",new View.OnClickListener(){@Overridepublic void onClick(View v) {//4.2.1.1 密碼輸入框請求獲取焦點;這個跟自動化測試切換句柄有點像etPassword.requestFocus();//4.2.1.2 獲取系統的某項服務InputMethodManager inputMethodManager = getSystemService(InputMethodManager.class);inputMethodManager.showSoftInput(etPassword,InputMethodManager.SHOW_IMPLICIT);}}).show();}}});// button.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// if(!userName.equals("admin") || !password.equals("123456")){
// Toast.makeText(ConstraintLoginActivity.this,"用戶名與密碼不匹配",Toast.LENGTH_SHORT).show();
// return;
// }
// startActivity(new Intent(ConstraintLoginActivity.this,TestActivity.class));
// }
// });}
注:在一個方法中,兩個監聽器同時監控同一個button,在代碼運行時會爆出一些程序崩潰的bug
2:Snackbar.make
snack 零食 bar 條 輕量級提示條 非常有意思的一種起名
第一個參數是當前頁面的任何一個View;第二個參數文本;第三個參數顯示的時間長短——短1.5s,長3s
3:setAction
Snackbar.setAction()
是用于為 Snackbar 添加可點擊操作按鈕的方法。Snackbar 是一種輕量級的提示組件,顯示在屏幕底部,而 setAction()
可以讓它變得交互式。
點擊“去輸入密碼”就會跳出來輸入法的使用
4:獲取焦點
焦點的概念:當前哪一個視圖在和用戶進行交互
我們要做的事情是,點擊去輸入密碼之后彈出輸入法,讓用戶去輸入密碼
etPassword代指密碼的TextView,requestFocus請求獲取焦點,
@Overridepublic void onClick(View v) {//4.2.1.1 密碼輸入框請求獲取焦點;這個跟自動化測試切換句柄有點像etPassword.requestFocus();//4.2.1.2 獲取系統的某項服務InputMethodManager inputMethodManager = getSystemService(InputMethodManager.class);inputMethodManager.showSoftInput(etPassword, InputMethodManager.SHOW_IMPLICIT);}
5:彈出軟鍵盤
(1)獲取服務
getSystemService 獲取系統的某項服務
InputMethodManager.class
是 Java 的類字面量(Class Literal)
//4.2.1.2 獲取系統的某項服務InputMethodManager inputMethodManager = getSystemService(InputMethodManager.class);inputMethodManager.showSoftInput(etPassword, InputMethodManager.SHOW_IMPLICIT);
(2)顯示方式
implicit [?m?pl?s?t] 隱式的
SHOW_IMPLICIT
理解成尊重用戶之前的操作習慣,可選擇的彈出或者不彈出輸入法
SHOW_FORCED
管你丫之前開沒開過輸入法,直接給你彈出來
二:AlertDialog彈窗的使用
1:完整代碼及效果
AlertDialog.Builder builder = new AlertDialog.Builder(AlertDialogActivity.this);builder.setTitle("是否刪除").setMessage("刪除后不能恢復")//設置積極的按鈕(積極消極其實就是按鈕的位置不同罷了,little problem).setPositiveButton("確定",new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {}}).setNegativeButton("取消",new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {}});AlertDialog alertDialog = builder.create();findViewById(R.id.btn_show).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {alertDialog.show();}});//關閉彈窗//alertDialog.dismiss();
顯示效果
2:AlertDialog.Builder-建房子
Alert 警覺的 Dialog 對話 翻譯為:警示對話框
導包選第二個;Androidx包下的樣式更豐富一點,相對來說更好用一點,傳入的參數是當前上下文,返回類型是Builder
3:setTitle和setMessage
設置標題和設置信息,如上方效果顯示的那樣;
4:Positive/NegativeButton
dialog下提供了兩種設置按鈕的形式
設置兩個按鈕,積極的那個按鈕默認放置在右邊,消極的按鈕默認放置在左邊;
通過按鈕設置監聽器,進而可以寫一些處理邏輯
5:builder.create()創建房子
其實很好理解,前面我們對build進行設置相當于打地基建房子裝修,create方法就是把這個暗中的房子創建出來;
下面設置的點擊按鈕事情,只是一個單純的觸發媒介,不必驚慌
AlertDialog alertDialog = builder.create();findViewById(R.id.btn_show).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {alertDialog.show();}});
默認情況下,無論點擊按鈕的哪個選項,關閉彈窗這件事情系統都會處理掉;
注:有時候需要手動的關閉彈窗,或者在其他時機關閉對話框時,就要調用 dismiss() 方法。
//關閉彈窗alertDialog.dismiss();
三:Toast彈窗提示
之前有詳細的講過,此處僅做對比
Toast.makeText(CheckBoxActivity.this, "請勾選協議!", Toast.LENGTH_SHORT).show();
三個參數:上下文(一般是當前類),彈窗內容,彈窗時間(有長有短)
show方法展示
四:DialogFragment管理彈窗(難)
提出問題:定義的彈窗可能會被多處使用,那么它的創建和銷毀,也就是生命周期的管理尤為重要。
這里我們介紹DialogFragment,一個專門用于創建對話框的抽象類;
Fragment在 Android 中,特指 “碎片”,是一種可嵌入 Activity 中的界面組件,用于構建靈活的界面(了解即可)
1:代碼
老規矩先上代碼
public class YesOrNoDialog extends DialogFragment {@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());builder.setTitle("是否刪除").setMessage("刪除后不能恢復")//設置積極的按鈕(積極消極其實就是按鈕的位置不同罷了,little problem).setPositiveButton("確定",new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {}}).setNegativeButton("取消",new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {}});AlertDialog alertDialog = builder.create();return alertDialog;}
}
public class DialogFragment extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_alert_dialog);Button fragmentDialog = findViewById(R.id.btn_show_dialog_fragment);fragmentDialog.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {YesOrNoDialog yesOrNoDialog = new YesOrNoDialog();yesOrNoDialog.show(getSupportFragmentManager(),"yesOrNo");}});}
}
2:對比分析
不要捉急
大局觀對比看代碼——((20250723152429-786dmu7 "我們在二:AlertDialog彈窗的使用 ")) 中裝修房子的任務丟給了一個方法,在類中調用這個方法
而下面這張圖片展示是把裝修房子的任務丟給了一個類中被重寫的方法,這個類繼承自DialogFragment;
這樣寫的好處
- 生命周期管理:自動處理對話框與 Activity 的生命周期綁定(如旋轉屏幕時保持狀態)。
3:繼承追溯
DialogFragment
是 Android 提供的一個抽象類,專門用于創建對話框,最終指向DIalog,是所有彈窗的父類,了解即可
4:onCreatDialog 重寫方法介紹
onCreateDialog()
是繼承父類后被重寫的方法,是 DialogFragment 的核心,用于創建并返回對話框實例,返回類型是Dialog;
固定寫法記住就好
import包導入第二個,否則重寫onCreateDIalog出不來(on首字母小寫)
5:getActivity
這里實例化一個Builder,需要傳參一個Activity類,可以理解成依附于 調用它的 Activity;這里使用getActivity()方法,指的就是DialogFragment類調用,就依附于DialogFragment這個類
AlertDialog.Builder builder = new AlertDialog.Builder(DialogFragment.this);
像直接在DialogFragment類中使用我們定義出來的方法,就直接傳參好了,如上述代碼
6:如何使用
YesOrNoDialog yesOrNoDialog = new YesOrNoDialog();yesOrNoDialog.show(getSupportFragmentManager(),"yesOrNo");
這兩行代碼是精髓,給show方法傳遞兩個參數,第一個參數獲取Fragment管理器,第二個參數tag,隨便取一個唯一的指就可以
(1)getSupportFragmentManager
返回一個FragmentManager對象,用于管理Activity中所有的Fragment(碎片)(包括DialogFragment-對話碎片)
作用
-
DialogFragment 需要依附于一個 Activity 來顯示,而 FragmentManager 就是連接兩者的橋梁。
其實就是中間商,因為FragmentManager還管理其他的碎片
-
FragmentManager 會跟蹤 DialogFragment 的生命周期(如創建、顯示、銷毀),并處理與其他 Fragment 的交互。
(2)TAG
這是一個 String 類型的標簽(tag) ,用于唯一標識這個 DialogFragment。
作用:
- 通過標簽,你可以在 FragmentManager 中查找并獲取這個 DialogFragment 的引用(例如使用
findFragmentByTag()
)。 - 標簽也會在日志或調試信息中顯示,方便追蹤問題。
7:容器化管理
(1)官方建議
官方建議不要在 Activity 或某個地方直接使用 Dialog,而是用‘容器’”
直接在 Activity 中創建 Dialog(如 AlertDialog)存在幾個問題:
-
生命周期脫節:
Dialog
是獨立于 Activity 生命周期的。例如,當屏幕旋轉(Activity 重建)時,直接創建的
Dialog
會被銷毀且不會自動重建,導致界面狀態丟失(比如對話框突然消失)。 -
內存泄漏風險:
如果Dialog
持有 Activity 的引用(如this
),而Dialog
的生命周期長于 Activity(比如 Activity 被銷毀但Dialog
未關閉),會導致 Activity 無法被 GC 回收,造成內存泄漏。 -
配置變更處理復雜:
屏幕旋轉、語言切換等配置變更時,需要手動保存和恢復Dialog
的狀態(如輸入內容、選中狀態),代碼繁瑣且易出錯。
這是一種思想,慢慢體會
(2)為什么 “容器化”(DialogFragment)更好?
- 自動跟隨生命周期:
DialogFragment
由 FragmentManager 管理,當 Activity 重建時,FragmentManager 會自動重建DialogFragment
及其內部的對話框,保持狀態一致性(比如旋轉屏幕后對話框仍在!!!這里理解非常好)。 - 避免內存泄漏:
DialogFragment
與 Activity 的綁定通過 FragmentManager 實現,遵循 Fragment 的生命周期規則,減少了不當引用導致的內存泄漏風險。