Android 官方推荐 : DialogFragment 创建对话框
标签: Android 官方推荐 : DialogFragment 创建对话框 HarmonyOS博客 51CTO博客
2023-07-18 18:24:26 84浏览
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)布局文件,我们创建一个设置名称的布局文件:
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:layout_width="wrap_content"
4. android:layout_height="wrap_content" >
5.
6. <TextView
7. android:id="@+id/id_label_your_name"
8. android:layout_width="wrap_content"
9. android:layout_height="32dp"
10. android:gravity="center_vertical"
11. android:text="Your name:" />
12.
13. <EditText
14. android:id="@+id/id_txt_your_name"
15. android:layout_width="match_parent"
16. android:layout_height="wrap_content"
17. android:layout_toRightOf="@id/id_label_your_name"
18. android:imeOptions="actionDone"
19. android:inputType="text" />
20.
21. <Button
22. android:id="@+id/id_sure_edit_name"
23. android:layout_width="wrap_content"
24. android:layout_height="wrap_content"
25. android:layout_alignParentRight="true"
26. android:layout_below="@id/id_txt_your_name"
27. android:text="ok" />
28.
29. </RelativeLayout>
b)继承DialogFragment,重写onCreateView方法
c)测试运行:
1. package com.example.zhy_dialogfragment;
2.
3. import android.app.DialogFragment;
4. import android.os.Bundle;
5. import android.view.LayoutInflater;
6. import android.view.View;
7. import android.view.ViewGroup;
8.
9. public class EditNameDialogFragment extends DialogFragment
10. {
11.
12.
13. @Override
14. public View onCreateView(LayoutInflater inflater, ViewGroup container,
15. Bundle savedInstanceState)
16. {
17. View view = inflater.inflate(R.layout.fragment_edit_name, container);
18. return view;
19. }
20.
21. }
Main方法中调用:
1. public void showEditDialog(View view)
2. {
3. new EditNameDialogFragment();
4. "EditNameDialog");
5. }
效果图:
可以看到,对话框成功创建并显示出来,不过默认对话框有个讨厌的标题,我们怎么去掉呢:可以在onCreateView中调用getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);即可去掉。即:
1. public class EditNameDialogFragment extends DialogFragment
2. {
3.
4. @Override
5. public View onCreateView(LayoutInflater inflater, ViewGroup container,
6. Bundle savedInstanceState)
7. {
8. getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
9. View view = inflater.inflate(R.layout.fragment_edit_name, container);
10. return view;
11. }
12.
13. }
效果图:
很完美的去掉了讨厌的标题。
4、 重写onCreateDialog创建Dialog
在onCreateDialog中一般可以使用AlertDialog或者Dialog创建对话框,不过既然google不推荐直接使用Dialog,我们就使用AlertDialog来创建一个登录的对话框。
a)布局文件
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:layout_width="wrap_content"
4. android:layout_height="wrap_content"
5. android:orientation="vertical" >
6.
7. <ImageView
8. android:layout_width="match_parent"
9. android:layout_height="64dp"
10. android:background="#FFFFBB33"
11. android:contentDescription="@string/app_name"
12. android:scaleType="center"
13. android:src="@drawable/title" />
14.
15. <EditText
16. android:id="@+id/id_txt_username"
17. android:layout_width="match_parent"
18. android:layout_height="wrap_content"
19. android:layout_marginBottom="4dp"
20. android:layout_marginLeft="4dp"
21. android:layout_marginRight="4dp"
22. android:layout_marginTop="16dp"
23. android:hint="input username"
24. android:inputType="textEmailAddress" />
25.
26. <EditText
27. android:id="@+id/id_txt_password"
28. android:layout_width="match_parent"
29. android:layout_height="wrap_content"
30. android:layout_marginBottom="16dp"
31. android:layout_marginLeft="4dp"
32. android:layout_marginRight="4dp"
33. android:layout_marginTop="4dp"
34. android:fontFamily="sans-serif"
35. android:hint="input password"
36. android:inputType="textPassword" />
37.
38. </LinearLayout>
b)继承DialogFragment重写onCreateDialog方法
1. package com.example.zhy_dialogfragment;
2.
3. import android.app.AlertDialog;
4. import android.app.Dialog;
5. import android.app.DialogFragment;
6. import android.content.DialogInterface;
7. import android.os.Bundle;
8. import android.view.LayoutInflater;
9. import android.view.View;
10. import android.view.ViewGroup;
11. import android.widget.EditText;
12.
13. public class LoginDialogFragment extends DialogFragment
14. {
15.
16. @Override
17. public Dialog onCreateDialog(Bundle savedInstanceState)
18. {
19. new AlertDialog.Builder(getActivity());
20. // Get the layout inflater
21. LayoutInflater inflater = getActivity().getLayoutInflater();
22. null);
23. // Inflate and set the layout for the dialog
24. // Pass null as the parent view because its going in the dialog layout
25. builder.setView(view)
26. // Add action buttons
27. "Sign in",
28. new DialogInterface.OnClickListener()
29. {
30. @Override
31. public void onClick(DialogInterface dialog, int id)
32. {
33. }
34. "Cancel", null);
35. return builder.create();
36. }
37. }
c)调用
1. public void showLoginDialog(View view)
2. {
3. new LoginDialogFragment();
4. "loginDialog");
5. }
效果图:
可以看到通过重写onCreateDialog同样可以实现创建对话框,效果还是很nice的。
5、传递数据给Activity
从dialog传递数据给Activity,可以使用“fragment interface pattern”的方式,下面通过一个改造上面的登录框来展示这种模式。
改动比较小,直接贴代码了:
1. package com.example.zhy_dialogfragment;
2.
3. import android.app.AlertDialog;
4. import android.app.Dialog;
5. import android.app.DialogFragment;
6. import android.content.DialogInterface;
7. import android.os.Bundle;
8. import android.view.LayoutInflater;
9. import android.view.View;
10. import android.view.ViewGroup;
11. import android.widget.EditText;
12.
13. public class LoginDialogFragment extends DialogFragment
14. {
15. private EditText mUsername;
16. private EditText mPassword;
17.
18. public interface LoginInputListener
19. {
20. void onLoginInputComplete(String username, String password);
21. }
22.
23. @Override
24. public Dialog onCreateDialog(Bundle savedInstanceState)
25. {
26. new AlertDialog.Builder(getActivity());
27. // Get the layout inflater
28. LayoutInflater inflater = getActivity().getLayoutInflater();
29. null);
30. mUsername = (EditText) view.findViewById(R.id.id_txt_username);
31. mPassword = (EditText) view.findViewById(R.id.id_txt_password);
32. // Inflate and set the layout for the dialog
33. // Pass null as the parent view because its going in the dialog layout
34. builder.setView(view)
35. // Add action buttons
36. "Sign in",
37. new DialogInterface.OnClickListener()
38. {
39. @Override
40. public void onClick(DialogInterface dialog, int id)
41. {
42. LoginInputListener listener = (LoginInputListener) getActivity();
43. listener.onLoginInputComplete(mUsername
44. .getText().toString(), mPassword
45. .getText().toString());
46. }
47. "Cancel", null);
48. return builder.create();
49. }
50. }
拿到username和password的引用,在点击登录的时候,把activity强转为我们自定义的接口:LoginInputListener,然后将用户输入的数据返回。
MainActivity中需要实现我们的接口LoginInputListener,实现我们的方法,就可以实现当用户点击登陆时,获得我们的帐号密码了:
效果:
1. c) MainActivity
2. package com.example.zhy_dialogfragment;
3.
4. import com.example.zhy_dialogfragment.LoginDialogFragment.LoginInputListener;
5.
6. import android.app.Activity;
7. import android.app.AlertDialog;
8. import android.content.DialogInterface;
9. import android.os.Bundle;
10. import android.view.LayoutInflater;
11. import android.view.View;
12. import android.widget.Toast;
13.
14. public class MainActivity extends Activity implements LoginInputListener
15. {
16.
17. @Override
18. protected void onCreate(Bundle savedInstanceState)
19. {
20. super.onCreate(savedInstanceState);
21. setContentView(R.layout.activity_main);
22. }
23.
24.
25.
26. public void showLoginDialog(View view)
27. {
28. new LoginDialogFragment();
29. "loginDialog");
30.
31. }
32.
33. @Override
34. public void onLoginInputComplete(String username, String password)
35. {
36. this, "帐号:" + username + ", 密码 :" + password,
37. Toast.LENGTH_SHORT).show();
38. }
39.
40. }
6、DialogFragment做屏幕适配
我们希望,一个对话框在大屏幕上以对话框的形式展示,而小屏幕上则直接嵌入当前的Actvity中。这种效果的对话框,只能通过重写onCreateView实现。下面我们利用上面的EditNameDialogFragment来显示。
EditNameDialogFragment我们已经编写好了,直接在MainActivity中写调用
1. public void showDialogInDifferentScreen(View view)
2. {
3. FragmentManager fragmentManager = getFragmentManager();
4. new EditNameDialogFragment();
5.
6. boolean mIsLargeLayout = getResources().getBoolean(R.bool.large_layout) ;
7. "TAG", mIsLargeLayout+"");
8. if (mIsLargeLayout )
9. {
10. // The device is using a large layout, so show the fragment as a
11. // dialog
12. "dialog");
13. else
14. {
15. // The device is smaller, so show the fragment fullscreen
16. FragmentTransaction transaction = fragmentManager
17. .beginTransaction();
18. // For a little polish, specify a transition animation
19. transaction
20. .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
21. // To make it fullscreen, use the 'content' root view as the
22. // container
23. // for the fragment, which is always the root view for the activity
24. transaction.replace(R.id.id_ly, newFragment)
25. .commit();
26. }
27. }
可以看到,我们通过读取R.bool.large_layout,然后根据得到的布尔值,如果是大屏幕则直接以对话框显示,如果是小屏幕则嵌入我们的Activity布局中
这个R.bool.large_layout是我们定义的资源文件:
在默认的values下新建一个bools.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <resources>
3.
4. <bool name="large_layout">false</bool>
5.
6. </resources>
然后在res下新建一个values-large,在values-large下再新建一个bools.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <resources>
3.
4. <bool name="large_layout">true</bool>
5.
6. </resources>
最后测试:
左边为模拟器,右边为我的手机~~~~~
7、屏幕旋转
当用户输入帐号密码时,忽然旋转了一下屏幕,帐号密码不见了~~~是不是会抓狂
传统的new AlertDialog在屏幕旋转时,第一不会保存用户输入的值,第二还会报异常,因为Activity销毁前不允许对话框未关闭。而通过DialogFragment实现的对话框则可以完全不必考虑旋转的问题。
我们直接把上面登录使用AlertDialog创建的登录框,拷贝到MainActivity中直接调用:
1. public void showLoginDialogWithoutFragment(View view)
2. {
3. new AlertDialog.Builder(this);
4. // Get the layout inflater
5. this.getLayoutInflater();
6.
7. // Inflate and set the layout for the dialog
8. // Pass null as the parent view because its going in the dialog layout
9. null))
10. // Add action buttons
11. "Sign in",
12. new DialogInterface.OnClickListener()
13. {
14. @Override
15. public void onClick(DialogInterface dialog, int id)
16. {
17. // sign in the user ...
18. }
19. "Cancel", null).show();
20. }
下面我分别点击两种方式创建的登录框,看效果图:
可以看到,传统的Dialog旋转屏幕时就消失了,且后台log会报异常~~~使用DialogFragment则不受影响。
好了,关于DialogFragment的介绍结束~~~~
有任何疑问请留言
5c币
源码点击下载
参考文档:
http://developer.android.com/guide/topics/ui/dialogs.html#DialogFragment
https://github.com/thecodepath/android_guides/wiki/Using-DialogFragment
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论
您可能感兴趣的博客