Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 官方推薦 : DialogFragment 怎樣創建對話框

Android 官方推薦 : DialogFragment 怎樣創建對話框

編輯:關於Android編程

1、 概述
DialogFragment在android 3.0時被引入。是一種特殊的Fragment,用於在Activity的內容之上展示一個模態的對話框。典型的用於:展示警告框,輸入框,確認框等等。
在DialogFragment產生之前,我們創建對話框:一般采用AlertDialog和Dialog。注:官方不推薦直接使用Dialog創建對話框。
2、 好處與用法
使用DialogFragment來管理對話框,當旋轉屏幕和按下後退鍵時可以更好的管理其聲明周期,它和Fragment有著基本一致的聲明周期。且DialogFragment也允許開發者把Dialog作為內嵌的組件進行重用,類似Fragment(可以在大屏幕和小屏幕顯示出不同的效果)。上面會通過例子展示這些好處~

使用DialogFragment至少需要實現onCreateView或者onCreateDIalog方法。onCreateView即使用定義的xml布局文件展示Dialog。onCreateDialog即利用AlertDialog或者Dialog創建出Dialog。

3、 重寫onCreateView創建Dialog

a)布局文件,我們創建一個設置名稱的布局文件:

 

[html]view plaincopy      
  1.  
  2. android:layout_width="wrap_content"
  3. android:layout_height="wrap_content">
  4.  
  5. android:id="@+id/id_label_your_name"
  6. android:layout_width="wrap_content"
  7. android:layout_height="32dp"
  8. android:gravity="center_vertical"
  9. android:text="Yourname:"/>
  10.  
  11. android:id="@+id/id_txt_your_name"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:layout_toRightOf="@id/id_label_your_name"
  15. android:imeOptions="actionDone"
  16. android:inputType="text"/>
  17.  
  18. android:id="@+id/id_sure_edit_name"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:layout_alignParentRight="true"
  22. android:layout_below="@id/id_txt_your_name"
  23. android:text="ok"/>
  24.  
  25.  
    b)繼承DialogFragment,重寫onCreateView方法

     

     

    [java]view plaincopy      
    1. packagecom.example.zhy_dialogfragment;
    2.  
    3. importandroid.app.DialogFragment;
    4. importandroid.os.Bundle;
    5. importandroid.view.LayoutInflater;
    6. importandroid.view.View;
    7. importandroid.view.ViewGroup;
    8.  
    9. publicclassEditNameDialogFragmentextendsDialogFragment
    10. {
    11.  
    12.  
    13. @Override
    14. publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,
    15. BundlesavedInstanceState)
    16. {
    17. Viewview=inflater.inflate(R.layout.fragment_edit_name,container);
    18. returnview;
    19. }
    20.  
    21. }  
      c)測試運行:

       

      Main方法中調用:

       

      [java]view plaincopy      
      1. publicvoidshowEditDialog(Viewview)
      2. {
      3. EditNameDialogFragmenteditNameDialog=newEditNameDialogFragment();
      4. editNameDialog.show(getFragmentManager(),"EditNameDialog");
      5. }   效果圖:

         

         

        \ 可以看到,對話框成功創建並顯示出來,不過默認對話框有個討厭的標題,我們怎麼去掉呢:可以在onCreateView中調用getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);即可去掉。即: [java]view plaincopy    
        1. publicclassEditNameDialogFragmentextendsDialogFragment
        2. {
        3.  
        4. @Override
        5. publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,
        6. BundlesavedInstanceState)
        7. {
        8. getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        9. Viewview=inflater.inflate(R.layout.fragment_edit_name,container);
        10. returnview;
        11. }
        12.  
        13. }  
          效果圖:   \ 很完美的去掉了討厭的標題。  
          4、 重寫onCreateDialog創建Dialog
          在onCreateDialog中一般可以使用AlertDialog或者Dialog創建對話框,不過既然google不推薦直接使用Dialog,我們就使用AlertDialog來創建一個登錄的對話框。

           

          a)布局文件

           

          [html]view plaincopy      
          1.  
          2. android:layout_width="wrap_content"
          3. android:layout_height="wrap_content"
          4. android:orientation="vertical">
          5.  
          6. android:layout_width="match_parent"
          7. android:layout_height="64dp"
          8. android:background="#FFFFBB33"
          9. android:contentDescription="@string/app_name"
          10. android:scaleType="center"
          11. android:src="@drawable/title"/>
          12.  
          13. android:id="@+id/id_txt_username"
          14. android:layout_width="match_parent"
          15. android:layout_height="wrap_content"
          16. android:layout_marginBottom="4dp"
          17. android:layout_marginLeft="4dp"
          18. android:layout_marginRight="4dp"
          19. android:layout_marginTop="16dp"
          20. android:hint="inputusername"
          21. android:inputType="textEmailAddress"/>
          22.  
          23. android:id="@+id/id_txt_password"
          24. android:layout_width="match_parent"
          25. android:layout_height="wrap_content"
          26. android:layout_marginBottom="16dp"
          27. android:layout_marginLeft="4dp"
          28. android:layout_marginRight="4dp"
          29. android:layout_marginTop="4dp"
          30. android:fontFamily="sans-serif"
          31. android:hint="inputpassword"
          32. android:inputType="textPassword"/>
          33.  
          34.  
            b)繼承DialogFragment重寫onCreateDialog方法

             

             

            [java]view plaincopy      
            1. packagecom.example.zhy_dialogfragment;
            2.  
            3. importandroid.app.AlertDialog;
            4. importandroid.app.Dialog;
            5. importandroid.app.DialogFragment;
            6. importandroid.content.DialogInterface;
            7. importandroid.os.Bundle;
            8. importandroid.view.LayoutInflater;
            9. importandroid.view.View;
            10. importandroid.view.ViewGroup;
            11. importandroid.widget.EditText;
            12.  
            13. publicclassLoginDialogFragmentextendsDialogFragment
            14. {
            15.  
            16. @Override
            17. publicDialogonCreateDialog(BundlesavedInstanceState)
            18. {
            19. AlertDialog.Builderbuilder=newAlertDialog.Builder(getActivity());
            20. //Getthelayoutinflater
            21. LayoutInflaterinflater=getActivity().getLayoutInflater();
            22. Viewview=inflater.inflate(R.layout.fragment_login_dialog,null);
            23. //Inflateandsetthelayoutforthedialog
            24. //Passnullastheparentviewbecauseitsgoinginthedialoglayout
            25. builder.setView(view)
            26. //Addactionbuttons
            27. .setPositiveButton("Signin",
            28. newDialogInterface.OnClickListener()
            29. {
            30. @Override
            31. publicvoidonClick(DialogInterfacedialog,intid)
            32. {
            33. }
            34. }).setNegativeButton("Cancel",null);
            35. returnbuilder.create();
            36. }
            37. }  
              c)調用

               

               

              [java]view plaincopy      
              1. publicvoidshowLoginDialog(Viewview)
              2. {
              3. LoginDialogFragmentdialog=newLoginDialogFragment();
              4. dialog.show(getFragmentManager(),"loginDialog");
              5. }  
                效果圖:

                 

                \

                 

                可以看到通過重寫onCreateDialog同樣可以實現創建對話框,效果還是很nice的。

                5、傳遞數據給Activity

                從dialog傳遞數據給Activity,可以使用“fragment interface pattern”的方式,下面通過一個改造上面的登錄框來展示這種模式。

                改動比較小,直接貼代碼了:

                 

                [java]view plaincopy      
                1. packagecom.example.zhy_dialogfragment;
                2.  
                3. importandroid.app.AlertDialog;
                4. importandroid.app.Dialog;
                5. importandroid.app.DialogFragment;
                6. importandroid.content.DialogInterface;
                7. importandroid.os.Bundle;
                8. importandroid.view.LayoutInflater;
                9. importandroid.view.View;
                10. importandroid.view.ViewGroup;
                11. importandroid.widget.EditText;
                12.  
                13. publicclassLoginDialogFragmentextendsDialogFragment
                14. {
                15. privateEditTextmUsername;
                16. privateEditTextmPassword;
                17.  
                18. publicinterfaceLoginInputListener
                19. {
                20. voidonLoginInputComplete(Stringusername,Stringpassword);
                21. }
                22.  
                23. @Override
                24. publicDialogonCreateDialog(BundlesavedInstanceState)
                25. {
                26. AlertDialog.Builderbuilder=newAlertDialog.Builder(getActivity());
                27. //Getthelayoutinflater
                28. LayoutInflaterinflater=getActivity().getLayoutInflater();
                29. Viewview=inflater.inflate(R.layout.fragment_login_dialog,null);
                30. mUsername=(EditText)view.findViewById(R.id.id_txt_username);
                31. mPassword=(EditText)view.findViewById(R.id.id_txt_password);
                32. //Inflateandsetthelayoutforthedialog
                33. //Passnullastheparentviewbecauseitsgoinginthedialoglayout
                34. builder.setView(view)
                35. //Addactionbuttons
                36. .setPositiveButton("Signin",
                37. newDialogInterface.OnClickListener()
                38. {
                39. @Override
                40. publicvoidonClick(DialogInterfacedialog,intid)
                41. {
                42. LoginInputListenerlistener=(LoginInputListener)getActivity();
                43. listener.onLoginInputComplete(mUsername
                44. .getText().toString(),mPassword
                45. .getText().toString());
                46. }
                47. }).setNegativeButton("Cancel",null);
                48. returnbuilder.create();
                49. }
                50. }  
                  拿到username和password的引用,在點擊登錄的時候,把activity強轉為我們自定義的接口:LoginInputListener,然後將用戶輸入的數據返回。

                   

                  MainActivity中需要實現我們的接口LoginInputListener,實現我們的方法,就可以實現當用戶點擊登陸時,獲得我們的帳號密碼了:

                   

                  [java]view plaincopy      
                  1. c)MainActivity
                  2. packagecom.example.zhy_dialogfragment;
                  3.  
                  4. importcom.example.zhy_dialogfragment.LoginDialogFragment.LoginInputListener;
                  5.  
                  6. importandroid.app.Activity;
                  7. importandroid.app.AlertDialog;
                  8. importandroid.content.DialogInterface;
                  9. importandroid.os.Bundle;
                  10. importandroid.view.LayoutInflater;
                  11. importandroid.view.View;
                  12. importandroid.widget.Toast;
                  13.  
                  14. publicclassMainActivityextendsActivityimplementsLoginInputListener
                  15. {
                  16.  
                  17. @Override
                  18. protectedvoidonCreate(BundlesavedInstanceState)
                  19. {
                  20. super.onCreate(savedInstanceState);
                  21. setContentView(R.layout.activity_main);
                  22. }
                  23.  
                  24.  
                  25.  
                  26. publicvoidshowLoginDialog(Viewview)
                  27. {
                  28. LoginDialogFragmentdialog=newLoginDialogFragment();
                  29. dialog.show(getFragmentManager(),"loginDialog");
                  30.  
                  31. }
                  32.  
                  33. @Override
                  34. publicvoidonLoginInputComplete(Stringusername,Stringpassword)
                  35. {
                  36. Toast.makeText(this,"帳號:"+username+",密碼:"+password,
                  37. Toast.LENGTH_SHORT).show();
                  38. }
                  39.  
                  40. }  
                    效果:

                     

                    \

                    6、DialogFragment做屏幕適配

                    我們希望,一個對話框在大屏幕上以對話框的形式展示,而小屏幕上則直接嵌入當前的Actvity中。這種效果的對話框,只能通過重寫onCreateView實現。下面我們利用上面的EditNameDialogFragment來顯示。

                    EditNameDialogFragment我們已經編寫好了,直接在MainActivity中寫調用

                     

                    [java]view plaincopy      
                    1. publicvoidshowDialogInDifferentScreen(Viewview)
                    2. {
                    3. FragmentManagerfragmentManager=getFragmentManager();
                    4. EditNameDialogFragmentnewFragment=newEditNameDialogFragment();
                    5.  
                    6. booleanmIsLargeLayout=getResources().getBoolean(R.bool.large_layout);
                    7. Log.e("TAG",mIsLargeLayout+"");
                    8. if(mIsLargeLayout)
                    9. {
                    10. //Thedeviceisusingalargelayout,soshowthefragmentasa
                    11. //dialog
                    12. newFragment.show(fragmentManager,"dialog");
                    13. }else
                    14. {
                    15. //Thedeviceissmaller,soshowthefragmentfullscreen
                    16. FragmentTransactiontransaction=fragmentManager
                    17. .beginTransaction();
                    18. //Foralittlepolish,specifyatransitionanimation
                    19. transaction
                    20. .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                    21. //Tomakeitfullscreen,usethe'content'rootviewasthe
                    22. //container
                    23. //forthefragment,whichisalwaystherootviewfortheactivity
                    24. transaction.replace(R.id.id_ly,newFragment)
                    25. .commit();
                    26. }
                    27. }  
                      可以看到,我們通過讀取R.bool.large_layout,然後根據得到的布爾值,如果是大屏幕則直接以對話框顯示,如果是小屏幕則嵌入我們的Activity布局中

                       

                      這個R.bool.large_layout是我們定義的資源文件:

                      在默認的values下新建一個bools.xml

                       

                      [html]view plaincopy      
                      1.  
                      2.  
                      3. false
                      4.  
                      5.  
                      6.  
                        然後在res下新建一個values-large,在values-large下再新建一個bools.xml

                         

                         

                        [html]view plaincopy      
                        1.  
                        2.  
                        3. true
                        4.  
                        5.  
                        6.  
                          最後測試:

                           

                          \ \

                          左邊為模擬器,右邊為我的手機~~~~~

                          7、屏幕旋轉

                          當用戶輸入帳號密碼時,忽然旋轉了一下屏幕,帳號密碼不見了~~~是不是會抓狂

                          傳統的new AlertDialog在屏幕旋轉時,第一不會保存用戶輸入的值,第二還會報異常,因為Activity銷毀前不允許對話框未關閉。而通過DialogFragment實現的對話框則可以完全不必考慮旋轉的問題。

                          我們直接把上面登錄使用AlertDialog創建的登錄框,拷貝到MainActivity中直接調用:

                           

                          [java]view plaincopy      
                          1. publicvoidshowLoginDialogWithoutFragment(Viewview)
                          2. {
                          3. AlertDialog.Builderbuilder=newAlertDialog.Builder(this);
                          4. //Getthelayoutinflater
                          5. LayoutInflaterinflater=this.getLayoutInflater();
                          6.  
                          7. //Inflateandsetthelayoutforthedialog
                          8. //Passnullastheparentviewbecauseitsgoinginthedialoglayout
                          9. builder.setView(inflater.inflate(R.layout.fragment_login_dialog,null))
                          10. //Addactionbuttons
                          11. .setPositiveButton("Signin",
                          12. newDialogInterface.OnClickListener()
                          13. {
                          14. @Override
                          15. publicvoidonClick(DialogInterfacedialog,intid)
                          16. {
                          17. //signintheuser...
                          18. }
                          19. }).setNegativeButton("Cancel",null).show();
                          20. }  
                            下面我分別點擊兩種方式創建的登錄框,看效果圖:

                             

                            \

                            可以看到,傳統的Dialog旋轉屏幕時就消失了,且後台log會報異常~~~使用DialogFragment則不受影響。

                             

                             

                            好了,關於DialogFragment的介紹結束~~~~

                             

                            有任何疑問請留言

                             

                            源碼點擊下載

                             

                            參考文檔:

                            http://developer.android.com/guide/topics/ui/dialogs.html#DialogFragment

                            https://github.com/thecodepath/android_guides/wiki/Using-DialogFragment

                             
          1. 上一頁:
          2. 下一頁:
          熱門文章
          閱讀排行版
          Copyright © Android教程網 All Rights Reserved