一、Dialog和DialogFragment
DialogFragment让dialog也变成了碎片,相比之前来说应该做了很多优化和处理,对于程序员来看对话框现在更加具体了,就是一个activity上的一个fragment,我们也可以用fragment的知识来管理对话框了。
Dialog运用对话框对象
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("Dialog")
.setMessage("thisis a dialog")
.show();```
这个时候屏幕方向发生变化,Activity重建,然后之前显示的对话框就不见了。查看log可以发现这个错误,我们也可以无视这个错误,因为程序不会因此崩溃(看来android本身就已经预料到这种情况了)。
如果我们想要在旋转屏幕的时候也能保证这个对话框显示就需要做一定的处理了,在activity要销毁前设立一个标志,看这时对话框是否是显示状态,如果是那么activity在下次建立时直接显示对话框。
在onSaveInstanceState中
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (dialog != null && dialog.isShowing()) {
outState.putBoolean("DIALOG_SHOWN", true);
}
}```
在onCreat中
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
boolean isShown = savedInstanceState.getBoolean("DIALOG_SHOWN");
if (isShown) {
AlertDialog dialog = new AlertDialog.Builder(this).setTitle("Dialog")
.setMessage("thisis a dialog").show();
}
}
……
}```
使用DialogFragment来管理对话框 就不会有这种问题了,代码也少了很多的逻辑处理。当你旋转屏幕的时候,fragmentManager会自定管理DialogFragment的生命周 期,如果当前已经显示在屏幕上了,那么旋转屏幕后夜会自动显示,下面就是在屏幕旋转时的log输出。
4-1917:45:41.289: D/==========(16156): MyDialogFragment : onAttach
04-1917:45:41.299: D/==========(16156): MyDialogFragment : onCreate
04-1917:45:41.299: D/==========(16156): MyDialogFragment : onCreateView
04-1917:45:41.309: D/==========(16156): MyDialogFragment : onStart
04-1917:45:50.619: D/==========(16156): MyDialogFragment : onStop
04-1917:45:50.619: D/==========(16156): third activity on destroy
04-1917:45:50.619:D/==========(16156): MyDialogFragment : onDestroyView
04-1917:45:50.619: D/==========(16156): MyDialogFragment : onDetach
04-1917:45:50.639: D/==========(16156): MyDialogFragment : onAttach
04-1917:45:50.639: D/==========(16156): MyDialogFragment : onCreate
04-1917:45:50.659: D/==========(16156): MyDialogFragment : onCreateView
04-1917:45:50.659: D/==========(16156): MyDialogFragment : onStart```
当然你可以不以为然,你说我的应用就是竖着用的,旋转屏幕毕竟是小概率事件,谁会开着对话框旋转来旋转去啊。那么相信下面的好处你一定不能否定吧。
我们之前用Dialog的时候,在activity中必须要建立这个对象,而且一般我们都是需要给它放监听器的,比如下面的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.guid_main);new AlertDialog.Builder(GuideActivity.this).setTitle("用户申明")
.setMessage(getResources().getString(R.string.statement))
.setPositiveButton("我同意", new positiveListener())
.setNegativeButton("不同意", new negativeListener())
.setCancelable(false)
.show();
}private class positiveListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
prefs.setIsFirstTime(false);
}
}
private class negativeListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
Util.virtualHome(GuideActivity.this);
}
}```
你会发现这么长的代码很破坏activity中 的逻辑性,在activity中我们处理的各种控件的显示和逻辑,但对于dialog这种不属于activity并且建立和处理逻辑都自成一 体的东西,我们为什么要在activity中建立呢?而且为了方便重用,我们在实际过程中基本都会建立一个dialog的工具类来做处理,所以为什么不用 DialogFragment来实现呢?如果通过它来实现,我们就能很方便的进行管理对话框。
此外,当 旋转屏幕和按下后退键时可以更好的管理其声明周期,它和Fragment有着基本一致的声明周期。且DialogFragment也允许开发者把 Dialog作为内嵌的组件进行重用,类似Fragment(可以在大屏幕和小屏幕显示出不同的效果)。有可能我们在大屏幕上就不需要弹出一个对话框了, 直接内嵌在activity界面中显示即可。
二、DialogFragment简单用法
使用DialogFragment很简单,甚至比用Fragment还简单,因为在api中已经实现了fragment切换对象了。
1.建立一个fragment对象
public class DialogFragment01 extends android.support.v4.app.DialogFragment{
private Button button;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//设置不显示标题
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
//设置本体之外不可点击
getDialog().setCanceledOnTouchOutside(false);
//设置返回键可点击
setCancelable(true);
//设置本体之外透明
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
View v = inflater.inflate(R.layout.mbin,null);
//实例化Button
button = (Button) v.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击取消
dismiss();
}
});
//设置动画
Animation animation = AnimationUtils.loadAnimation(getActivity(),R.anim.gert_poop);
animation.setDuration(5000);
v.startAnimation(animation);
return v;
}
@Override
public void onStart() {
super.onStart();
//设置匹配父级元素
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
}
}
我们建立了一个fragment,让他继承了DialogFragment,在onCreatView中通过布局文件建立了一个view,这和fragment完全一致。
android:layout_height="match_parent"
android:gravity="center"
>
android:layout_width="400dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/dar"
>
android:text="DialogFragment"
android:textSize="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"/>
动画设置
android:toYDelta="0%p"
/>
```
2.在activity中启用这个dialog
package com.liaxi.dell.dialogfragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mian);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
DialogFragment01 dialogFragment0102=new DialogFragment01();
dialogFragment0102.show(getSupportFragmentManager(),"");
}
}
运行效果如下
源码下载:https://github.com/gb0302/DialogFragment