关于DialogFragment的一些学习
标签(空格分隔): DialogFrgment
经历了一个月的项目期,Google给我的最好礼物莫过于谷歌官方网站了
点击进入Google官网DialogFragment介绍
自从Fragment时代的到来,任何View都可以封装到一个Fragment中,然后代替原来的固定的布局模式;DialogFragment因为继承于Fragment并封装了一个Dialog, 所以,有两种方式可以启动DialogFragment.
调用DialogFragment的show()方法,覆盖模式
void showDialog() {
// Create the fragment and show it as a dialog.
DialogFragment newFragment = MyDialogFragment.newInstance();
newFragment.show(getFragmentManager(), "dialog");
}
show方法的实现
public void show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
}
按照Fragment的加载方式,加载到内容区域
FragmentTransaction ft = getFragmentManager().beginTransaction();
DialogFragment newFragment = MyDialogFragment.newInstance();
ft.add(R.id.embedded, newFragment);
ft.commit();
在Dialog的构造方法中,实例化了一个属于自己的Window对象,这个很重要。
Dialog(Context context, int theme, boolean createContextThemeWrapper) {
····
mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}
public class Dialog implements DialogInterface, Window.Callback,
KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {}
上面这段代码,表明Dialog能够接受Window的Callback,消失事件,按键事件(优先于宿主Activity)
这表明Dialog可以做很多事情,因为它拥有属于自己的Window,能够监听按键的事件,大家都有各种方式让Fragment变相监听到返回键。如何只需要一个页面的话,也可以考虑DialogFragment。
Demo: 设置Window的大小
Window window = getDialog().getWindow();
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
getDialog().getWindow().setLayout(dm.widthPixels,
getDialog().getWindow().getAttributes().height);
window.setBackgroundDrawable(new ColorDrawable(0xff000000));
WindowManager.LayoutParams layoutParams = window.getAttributes();
// 底部显示
layoutParams.gravity = Gravity.BOTTOM;
layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.windowAnimations = com.jiuyuhulian.LiveRoom.R.style.BottomToTopAnim;
window.setAttributes(layoutParams);
DialogFragment实现的接口方法。
public void onCancel(DialogInterface dialog) {
}
public void onDismiss(DialogInterface dialog) {
if (!mViewDestroyed) {
// Note: we need to use allowStateLoss, because the dialog
// dispatches this asynchronously so we can receive the call
// after the activity is paused. Worst case, when the user comes
// back to the activity they see the dialog again.
dismissInternal(true);
}
}
对比, 简单的解释就是,当我们锁屏的时候,我们的Dialog会调用dismissAllowingStateLoss(), 当解锁时,DialogFragment会再次显示出来,而dissmiss则会不保存这个状态。
public void dismiss() {
dismissInternal(false);
}
public void dismissAllowingStateLoss() {
dismissInternal(true);
}
dismissInternal(boolean allowStateLoss)
void dismissInternal(boolean allowStateLoss) {
if (mDismissed) {
return;
}
mDismissed = true;
mShownByMe = false;
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
mViewDestroyed = true;
if (mBackStackId >= 0) {
getFragmentManager().popBackStack(mBackStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
mBackStackId = -1;
} else {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(this);
if (allowStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
}
}
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
监听返回键
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent) {
// 这里会优先监听到Key事件,最主要的是back键,注意back键有down和up事件
return false;
}
});
设置要在getLayoutInflater()方法之前,也就是在页面初始化之前
public void setStyle(int style, int theme) {
mStyle = style;
if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
mTheme = com.android.internal.R.style.Theme_DeviceDefault_Dialog_NoFrame;
}
if (theme != 0) {
mTheme = theme;
}
}
public static final int STYLE_NO_TITLE = 1; // 没标题
public static final int STYLE_NO_FRAME = 2; // 无框的(没有层级)
public static final int STYLE_NO_INPUT = 3; // 不可输入