本文實例講述了Android開發之DialogFragment用法。分享給大家供大家參考,具體如下:
背景
Android 官方推薦使用 DialogFragment 來代替 Dialog ,可以讓它具有更高的可復用性(降低耦合)和更好的便利性(很好的處理屏幕翻轉的情況)。
而創建 DialogFragment 有兩種方式:
1. 覆寫其 onCreateDialog 方法 ― ①
2. 覆寫其 onCreateView 方法 ― ②
雖然這兩種方式都能實現相同的效果,但是它們各有自己適合的應用場景:
1. 方法 ①,一般用于創建替代傳統的 Dialog 對話框的場景,UI 簡單,功能單一。
2. 方法 ②,一般用于創建復雜內容彈窗或全屏展示效果的場景,UI 復雜,功能復雜,一般有網絡請求等異步操作。
應用
基本用法
對于方法 ①,創建一個 Dialog 并返回它即可:
@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) { //為了樣式統一和兼容性,可以使用 V7 包下的 AlertDialog.Builder AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); // 設置主題的構造方法 // AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomDialog); builder.setTitle("注意:") .setMessage("是否退出應用?") .setPositiveButton("確定", null) .setNegativeButton("取消", null) .setCancelable(false); //builder.show(); // 不能在這里使用 show() 方法 return builder.create();}當然,你也可以使用自定義 View 來創建:
@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); // 設置主題的構造方法 // AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomDialog); LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.fragment_dialog, null); builder.setView(view) // Do Someting,eg: TextView tv = view.findViewById(R.id.tv); return builder.create();}PS:創建 Dialog 的方式有多種,比如下面這種,使用時略有差異,需要自己注意:
@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.fragment_dialog, null); Dialog dialog = new Dialog(getActivity()); // 設置主題的構造方法 // Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog); dialog.setContentView(view); // Do Someting return dialog;}對于方法 ②,和普通的 Fragment 用法基本一致:
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_dialog, container, false); // Do Someting return rootView;}/** * 設置主題需要在 onCreate() 方法中調用 setStyle() 方法 */@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);}處理屏幕翻轉
如果使用傳統的 Dialog ,需要我們手動處理屏幕翻轉的情況,但使用 DialogFragment 的話,則不需要我們進行任何處理,FragmentManager 會自動管理 DialogFragment 的生命周期。
無標題欄/全屏
在基本用法里代碼注釋有設置主題的地方,下面詳細說下兩種方法下設置無標題欄和實現全屏的方式:
無標題欄
對于方法 ① :
@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.fragment_dialog, null); Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog); // 關閉標題欄,setContentView() 之前調用 dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(true); return dialog;}對于方法 ②:
@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * setStyle() 的第一個參數有四個可選值: * STYLE_NORMAL|STYLE_NO_TITLE|STYLE_NO_FRAME|STYLE_NO_INPUT * 其中 STYLE_NO_TITLE 和 STYLE_NO_FRAME 可以關閉標題欄 * 每一個參數的詳細用途可以直接看 Android 源碼的說明 */ setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);}實現全屏(寬/高度全屏)
常用的形式大多是寬度上和屏幕一樣寬,高度自適應,下面直接看代碼:
方法 ① :
@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.fragment_dialog, null); Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(true); //Do something // 設置寬度為屏寬、位置靠近屏幕底部 Window window = dialog.getWindow(); window.setBackgroundDrawableResource(R.color.transparent); WindowManager.LayoutParams wlp = window.getAttributes(); wlp.gravity = Gravity.BOTTOM; wlp.width = WindowManager.LayoutParams.MATCH_PARENT; wlp.height = WindowManager.LayoutParams.WRAP_CONTENT; window.setAttributes(wlp); return dialog;}代碼 12 行設置了窗口的背景色為透明,這一步是必須的;
代碼 15 行設置窗口的寬度為 MATCH_PARENT,效果是和屏幕寬度一樣大,同樣你也可以設置高度的值。設置寬度和高度除了 MATCH_PARENT 和 WRAP_CONTENT ,也可以直接設置成具體的數值。
方法 ②:
@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { getDialog().setCanceledOnTouchOutside(true); View rootView = inflater.inflate(R.layout.fragment_dialog, container, false); //Do something // 設置寬度為屏寬、靠近屏幕底部。 final Window window = getDialog().getWindow(); window.setBackgroundDrawableResource(R.color.transparent); window.getDecorView().setPadding(0, 0, 0, 0); WindowManager.LayoutParams wlp = window.getAttributes(); wlp.gravity = Gravity.BOTTOM; wlp.width = WindowManager.LayoutParams.MATCH_PARENT; wlp.height = WindowManager.LayoutParams.WRAP_CONTENT; window.setAttributes(wlp); return rootView;}代碼 14 行設置了窗口的背景色為透明,這一步是必須的;
代碼 15 行設置了窗口的 Pading 值全部為0,這一步也是必須的,內容不能填充全部寬度和高度。
其他的和 ① 中的類似。
應用場景區別
文章一開始簡單總結了方法 ① 和方法 ② 的應用場景,這里說明下:
1. 從基本的用法中可以看到方法 ① 為簡單的替代 Dialog 提供了非常方便的創建方式,比方法 ② 有優勢
2. 方法 ① 在使用了多線程(例如網絡請求)的情況下,不能正確的獲取當前 Fragment 的狀態,會產生空指針異常。方法 ② 則沒有此問題,而且,其創建方式默認使用了自定義 View,更便于應對復雜 UI 的場景。
這里舉例說明:方法 ① 和方法 ② 的//Do something 代碼處,我們進行一些異步操作:
TextView title = rootView.findViewById(R.id.dialoag_tv);title.setText("Value A");new SomeTask().execute(url);private class SomeTask extends AsyncTask<String, Void, Boolean> { @Override protected Boolean doInBackground(String... params) { // 一些網絡請求 // 成功時 return true; // 異常時 return false; } @Override protected void onPostExecute(Boolean aBoolean) { super.onPostExecute(aBoolean); // if (!isVisible()) return; if (aBoolean) { title.setText("Value B"); } }}如果在網絡請求未結束或者剛結束時關閉了當前 DialogFragment ,代碼 19 行就會報空指針異常了,代碼 17 的作用就是判斷 DialogFragment 當前的狀態是否為可用態,但是 isVisible() 以及 isHide() 對于方法 ① 無法正確返回其狀態,方法 ② 則正常。方法 ① 和方法 ② 創建 DialogFragment 的一些狀態并不是完全一致。
PS:你也可以使用靜態 Handler 結合弱引用等來處理異步操作,那樣對 DialogFragment 狀態的獲取就不重要了。
總結
以上是個人在實際開發過程中的一點總結和看法,希望你能抱著存疑的態度進行嘗試,如果有新的觀點或者文章中有不正確的地方,歡迎和我聯系。
更多關于Android相關內容感興趣的讀者可查看本站專題:《Android開發入門與進階教程》、《Android調試技巧與常見問題解決方法匯總》、《Android基本組件用法總結》、《Android視圖View技巧總結》、《Android布局layout技巧總結》及《Android控件用法總結》
希望本文所述對大家Android程序設計有所幫助。
新聞熱點
疑難解答