Android 官方推薦 : DialogFragment 怎樣建立對話方塊

來源:互聯網
上載者:User

Android 官方推薦 : DialogFragment 怎樣建立對話方塊
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.  
                          最後測試:

                           

                          左邊為模擬器,右邊為My Phone~~~~~

                          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

                             

          聯繫我們

          該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

          如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

          A Free Trial That Lets You Build Big!

          Start building with 50+ products and up to 12 months usage for Elastic Compute Service

          • Sales Support

            1 on 1 presale consultation

          • After-Sales Support

            24/7 Technical Support 6 Free Tickets per Quarter Faster Response

          • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.