热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

详解Android应用中DialogFragment的基本用法

AndroidApp中建议使用DialogFragment作为对话框的容器,DialogFragment类提供了创建对话框并管理其外观需要的所有控件,本文主要内容便为详解Android应用中DialogFragment的基本用法,而不再需要调用Dialog的方法需要的朋友可以参考下

DialogFragment的基本用法
1. 创建DialogFragment

public class DialogA extends DialogFragment implements DialogInterface.OnClickListener {

 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
  builder.setMessage(R.string.dialoga_title)
    .setPositiveButton(R.string.ok, this)
    .setNegativeButton(R.string.cancel, this);

  return builder.create();
 } 

 @Override
 public void onClick(DialogInterface dialog, int id) {
  switch(id) {
   case AlertDialog.BUTTON_NEGATIVE:
    Toast.makeText(getActivity(), "Negative", Toast.LENGTH_SHORT).show();
    break;
   case AlertDialog.BUTTON_POSITIVE:
    Toast.makeText(getActivity(), "Positive", Toast.LENGTH_SHORT).show();
    break;
   default:
    break;
  } 
 } 
}

说明:自定义一个DialogFragment,并重写它的onCreateDialog()方法。
2. 调用该DialogFragment
下面是在FragmentActivity中调用该DialogFragment对话框。

public class DialogTest extends FragmentActivity {

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  showDialog();
 }

 private void showDialog() {
  FragmentManager fm = getSupportFragmentManager();
  DialogA dialoga = new DialogA();
  dialoga.show(fm, "fragmenta");
 }
}

自定义DialogFragment布局
下面介绍自定义DialogFragment的布局的方法
点击查看:自定义DialogFragment布局的完整代码
1. 设置布局文件

<&#63;xml version="1.0" encoding="utf-8"&#63;>


 

 



2. 使用布局

public class DialogA extends DialogFragment implements DialogInterface.OnClickListener {

 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
  LayoutInflater inflater = getActivity().getLayoutInflater();
  builder.setView(inflater.inflate(R.layout.dialoga, null))
    .setMessage(R.string.dialoga_title)
    .setPositiveButton(R.string.ok, this)
    .setNegativeButton(R.string.cancel, this);

  return builder.create();
 }

 @Override
 public void onClick(DialogInterface dialog, int id) {
  switch(id) {
   case AlertDialog.BUTTON_NEGATIVE:
    Toast.makeText(getActivity(), "Negative", Toast.LENGTH_SHORT).show();
    break;
   case AlertDialog.BUTTON_POSITIVE:
    Toast.makeText(getActivity(), "Positive", Toast.LENGTH_SHORT).show();
    break;
   default:
    break;
  }
 }
}

DialogFragment和Activity的交互
下面介绍自定义DialogFragment和Activity交互的方法
点击查看:DialogFragment和Activity交互的完整代码
1. 定义通信接口
在DialogFragment中定义它们之间的通信接口。

public interface NoticeDialogListener {
 public void onDialogPositiveClick(DialogFragment dialog);
 public void onDialogNegativeClick(DialogFragment dialog);
} 

// Use this instance of the interface to deliver action events
NoticeDialogListener mListener;

// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
@Override
public void onAttach(Activity activity) {
 super.onAttach(activity);
 // Verify that the host activity implements the callback interface
 try {
  // Instantiate the NoticeDialogListener so we can send events to the host
  mListener = (NoticeDialogListener) activity;
 } catch (ClassCastException e) {
  // The activity doesn't implement the interface, throw exception
  throw new ClassCastException(activity.toString()
    + " must implement NoticeDialogListener");
 } 
} 

2. 在DialogFragment中调用该接口

@Override
public void onClick(DialogInterface dialog, int id) {
 switch(id) {
  case AlertDialog.BUTTON_POSITIVE:
   //Toast.makeText(getActivity(), "Negative", Toast.LENGTH_SHORT).show();
   mListener.onDialogPositiveClick(DialogA.this);
   break;
  case AlertDialog.BUTTON_NEGATIVE:
   //Toast.makeText(getActivity(), "Positive", Toast.LENGTH_SHORT).show();
   mListener.onDialogNegativeClick(DialogA.this);
   break;
  default:
   break;
 } 
}

3. 在Activity中实现该接口

public class DialogTest extends FragmentActivity 
 implements DialogA.NoticeDialogListener {

 ...

 @Override
 public void onDialogPositiveClick(DialogFragment dialog) {
  Toast.makeText(this, "Positive Callback", Toast.LENGTH_SHORT).show();
 }
 @Override
 public void onDialogNegativeClick(DialogFragment dialog) {
  Toast.makeText(this, "Negative Callback", Toast.LENGTH_SHORT).show();
 }
}

Dialog与DialogFragment的对比
从代码的编写角度看,Dialog使用起来要更为简单,但是Google则是推荐尽量使用DialogFragment(对于Android 3.0以下的版本,可以结合使用support包中提供的DialogFragment以及FragmentActivity)。今天试着用这两种方式来创建对话框,发现DialogFragment果然有一个非常好的特性(在手机配置变化,导致Activity需要重新创建时,例如旋屏,基于DialogFragment的对话框将会由FragmentManager自动重建,然而基于Dialog实现的对话框则没有这样的能力)。

下面是两段实例代码:

他们使用的界面都一样:(dialog.xml)

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
 
 

1.基于Dialog实现的对话框

public class MainActivity extends Activity {
 private Button clk;
 private Dialog dialog;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   
  clk = (Button) findViewById(R.id.clk);
  dialog = new Dialog(this);
  dialog.setContentView(R.layout.dialog);
  clk.setOnClickListener(new OnClickListener() {
    
   @Override
   public void onClick(View v) {
    dialog.show();
   }
  });
 }
}

当我们点击按钮时,会弹出对话框(内容为android logo),当我们旋转屏幕后,Activity重新创建,整个Activity的界面没有问题,而对话框消失了。
除此之外,其实还有一个问题,就是在logcat中会看到异常信息:Android..leaked .. window,这是因为在Activity结束之前,Android要求所有的Dialog必须要关闭。我们旋屏后,Activity会被重建,而上面的代码逻辑并没有考虑到对话框的状态以及是否已关闭。

于是将上述代码修改为:

public class MainActivity extends Activity {
 private Button clk;
 private Dialog dialog;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   
  clk = (Button) findViewById(R.id.clk);
  dialog = new Dialog(this);
  dialog.setContentView(R.layout.dialog);
  clk.setOnClickListener(new OnClickListener() {
    
   @Override
   public void onClick(View v) {
    dialog.show();
   }
  });
 
  //用户恢复对话框的状态
  if(savedInstanceState != null && savedInstanceState.getBoolean("dialog_show"))
   clk.performClick();
 }
 
 /**
  * 用于保存对话框的状态以便恢复
  */
 @Override
 protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  if(dialog != null && dialog.isShowing())
   outState.putBoolean("dialog_show", true);
  else
   outState.putBoolean("dialog_show", false);
 }
 
 /**
  * 在Activity销毁之前,确保对话框以关闭
  */
 @Override
 protected void onDestroy() {
  super.onDestroy();
  if(dialog != null && dialog.isShowing())
   dialog.dismiss();
 }
}


2. 基于DialogFragment的对话框

与上面的对话框使用同样的界面布局,此处仅仅展现一个简单对话框,因此只重写了onCreateView方法

public class MyDialogFragment extends DialogFragment {
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View v = inflater.inflate(R.layout.dialog, container, false);
  return v;
 }
}

public class MainActivity extends FragmentActivity {
 private Button clk;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
   
  clk = (Button) findViewById(R.id.clk);
  clk.setOnClickListener(new OnClickListener() {
    
   @Override
   public void onClick(View v) {
    MyDialogFragment mdf = new MyDialogFragment();
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    mdf.show(ft, "df");
   }
  });
 }
}


这两段代码可以实现第一种方式的同样功能,此处我们并没有去关心对话框的重建,以及Activity销毁前对话框是否已关闭,这一切都是由FragmentManager来管理。
其实DialogFragment还拥有fragment的优点,即可以在一个Activity内部实现回退(因为FragmentManager会管理一个回退栈)


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文是关于自学Android的笔记,包括查看类的源码的方法,活动注册的必要性以及布局练习的重要性。通过学习本文,读者可以了解到在自学Android过程中的一些关键点和注意事项。 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
author-avatar
小涵竹叶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有