标签:
一、重写一个类继承自android.support.v4.app.DialogFragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.dialog_fragment_profile, container);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//view中的控件进行一系列初始化
}@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments().getString("title"); //之前通过setArguments传入的参数
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setMessage("Are you sure?");
alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// on success
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return alertDialogBuilder.create();
}<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- Apply default style for dialogs -->
<item name="android:dialogTheme">@style/AppDialogTheme</item>
</style>
<style name="EvanBaseDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<!--此处的值也控制ActionBar背景-->
<item name="colorPrimary">@color/colorPrimary</item>
<!--此处的值也控制ActionBar上面显示电量、信号那行视图的背景-->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!--控制比如editText被选中状态下下面那条线的颜色-->
<item name="colorAccent">@color/red</item>
<!--控制比如editText中长按选中的那部分文字的颜色,一般对其进行复制粘贴操作-->
<item name="android:textColorHighlight">@color/purple</item>
<!--控制比如editText正常状态下下面那条线的颜色-->
<item name="colorControlNormal">@color/white</item>
<!-- Define window properties as desired -->
<item name="android:windowNoTitle">false</item>
<item name="android:windowTitleStyle">@style/EvanBaseDialogWindowTitle</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowCloseOnTouchOutside">true</item>
<!--此处设置为真则背景是灰色,没有阴影效果-->
<item name="android:windowIsTranslucent">true</item>
<!--整个对话框的背景颜色-->
<item name="android:windowBackground">@drawable/white_corners_background</item>
</style>
<style name="EvanBaseDialogWindowTitle" parent="Base.DialogWindowTitle.AppCompat">
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center</item>
<!--整个title部分的背景颜色-->
<item name="android:background">@color/white</item>
<!--title文字显示的样子 大小等-->
<item name="android:textAppearance">@style/EvanBaseDialogWindowTitleText</item>
</style>
<style name="EvanBaseDialogWindowTitleText" parent="@android:style/TextAppearance.DialogWindowTitle">
<item name="android:textSize">@dimen/big_textSize</item>
</style>FragmentManager fm = mActivity.getSupportFragmentManager();
MyDialogFragment mDialog = MyDialogFragment.newInstance("Some title"); //DialogFragment的创建一般都是通过getInstance方法创建。
mDialog.show(fm, "fragment_tag");ProgressDialog pd = new ProgressDialog(context); pd.setTitle("Loading..."); pd.setMessage("Please wait."); pd.setCancelable(false); pd.show(); or pd.dismiss();
show()@DialogFragment.class
public void show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag); //note1
ft.commit();
}1、添加的Fragment是没有containerID的。onCreateView方法的参数ViewGroup container为null,表明onCreateView所创建出来的View显示到所属Activity的布局中的某个View中。既然如此,那肯定是DialogFrament通过重写父类Fragment的生命周期中的某些方法,在方法内部动态向手机屏幕上显示对话框视图,往下我们就对Fragment中的方法进行说明。对于Fragment的生命周期等感兴趣的可以参考本人另外一篇博客:http://blog.csdn.net/evan_man/article/details/51329320常用域以及其初始化@DialogFrament.class
public static final int STYLE_NORMAL = 0; public static final int STYLE_NO_TITLE = 1; public static final int STYLE_NO_FRAME = 2; public static final int STYLE_NO_INPUT = 3; int mStyle = STYLE_NORMAL; int mTheme = 0; boolean mCancelable = true; boolean mShowsDialog = true; int mBackStackId = -1; Dialog mDialog; //Dialog显示的关键 boolean mViewDestroyed; boolean mDismissed; boolean mShownByMe;
onAttach()@DialogFrament.class
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!mShownByMe) { //正常情况不会跳转到这里
mDismissed = false;
}
}onCreate()@DialogFrament.class
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mShowsDialog = mContainerId == 0; //note1
if (savedInstanceState != null) { //恢复之前的设置,第一次创建将不会进入到这里
mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);
mTheme = savedInstanceState.getInt(SAVED_THEME, 0);
mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);
mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);
}
}getLayoutInflater()@DialogFrament.class
public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
if (!mShowsDialog) { //根据前面的分析正常情况下mShowsDialog为真
return super.getLayoutInflater(savedInstanceState);
}
mDialog = onCreateDialog(savedInstanceState); //note1
if (mDialog != null) {
setupDialog(mDialog, mStyle); //note2
return (LayoutInflater) mDialog.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE); //返回所属dialog的LayoutInflate对象,用于解析onCreateView中的xml布局文件
}
return (LayoutInflater) mHost.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE); //返回所属context的LayoutInflate对象,用于解析onCreateView中的xml布局文件
}1、调用onCreateDialog方法创建一个特定的Dialog对象@NonNullpublic Dialog onCreateDialog(Bundle savedInstanceState) {return new Dialog(getActivity(), getTheme()); //参数分别为当前DialogFragment所属Context、以及自身属性int mTheme = 0;}创建了一个android.app.Dialog对象
public void setupDialog(Dialog dialog, int style) {switch (style) {case STYLE_NO_INPUT:dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);case STYLE_NO_FRAME:case STYLE_NO_TITLE:dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);}}
onActivityCreated()@DialogFragment.class
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (!mShowsDialog) {
return;
}
View view = getView(); //onCreateView创建出来的view
if (view != null) {
if (view.getParent() != null) {
throw new IllegalStateException("DialogFragment can not be attached to a container view");
}
mDialog.setContentView(view); //将view交给dialog显示
}
mDialog.setOwnerActivity(getActivity());
mDialog.setCancelable(mCancelable);
mDialog.setOnCancelListener(this);
mDialog.setOnDismissListener(this);
if (savedInstanceState != null) { //同样的初次启动不会进入到这里的代码
Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG);
if (dialogState != null) {
mDialog.onRestoreInstanceState(dialogState);
}
}
}这个方法的功能也就是对前面getLayoutInflater方法中创建的dialog进行设置、将onCreateView方法创建的View进行绑定、设置监听器等。onStart()@DialogFragment.class
@Override
public void onStart() {
super.onStart();
if (mDialog != null) {
mViewDestroyed = false;
mDialog.show(); //note1
}
}onStop()@DialogFragment.class
@Override
public void onStop() {
super.onStop();
if (mDialog != null) {
mDialog.hide();
}
}onDestroyView()@DialogFragment.class
@Override
public void onDestroyView() {
super.onDestroyView();
if (mDialog != null) {
mViewDestroyed = true;
mDialog.dismiss();
mDialog = null;
}
}onDetach()@DialogFragment.class
@Override
public void onDetach() {
super.onDetach();
if (!mShownByMe && !mDismissed) {
mDismissed = true;
}
}final Context mContext; final WindowManager mWindowManager; Window mWindow; private Handler mListenersHandler;
Dialog()@Dialog.class
public Dialog(@NonNull Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == 0) { //通过DialogFragment创建的一般都是这种情况
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true); //从context的主题中获取到dialogTheme属性
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId); //利用初始化mContext带主题
} else {
mContext = context;
}
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); //负责窗口管理服务
final Window w = new PhoneWindow(mContext); //创建PhoneWindow,用于具体显示
mWindow = w;
w.setCallback(this); //dialog实现了Window.Callback接口,里面定义了如dispatchKeyEvent等处理用户点击事件的操作
w.setOnWindowDismissedCallback(this); //处理窗口销毁时的接口
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}public void setContentView(View view) {
mWindow.setContentView(view); //调用PhoneWindow的同名方法
}private Activity mOwnerActivity;
public final void setOwnerActivity(Activity activity) {
mOwnerActivity = activity;
mWindow.setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
}protected boolean mCancelable = true;
public void setCancelable(boolean flag) {
mCancelable = flag;
}
private String mCancelAndDismissTaken;
private Message mCancelMessage; //用于存储一个取消Message,在Dialog销毁时将该Message交给Handler处理
public void setOnCancelListener(final OnCancelListener listener) {
if (mCancelAndDismissTaken != null) {
throw new IllegalStateException(
"OnCancelListener is already taken by "
+ mCancelAndDismissTaken + " and can not be replaced.");
}
if (listener != null) {
mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
} else {
mCancelMessage = null;
}
}private Message mDismissMessage;
public void setOnDismissListener(final OnDismissListener listener) {
if (mCancelAndDismissTaken != null) {
throw new IllegalStateException(
"OnDismissListener is already taken by "
+ mCancelAndDismissTaken + " and can not be replaced.");
}
if (listener != null) {
mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
} else {
mDismissMessage = null;
}
}private boolean mShowing = false;
private boolean mCreated = false;
View mDecor;
public void show() {
if (mShowing) { //第一次调用不会进入到这里
if (mDecor != null) {
if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
}
mDecor.setVisibility(View.VISIBLE);
}
return;
}
mCanceled = false;
if (!mCreated) { //第一次调用会执行下面的代码
dispatchOnCreate(null); //note1
}
onStart(); //note2
mDecor = mWindow.getDecorView(); //从PhoneWindows中获取DecorView
if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { //ActionBar为null,同时当前PhoneWindow拥有标题栏
final ApplicationInfo info = mContext.getApplicationInfo();
mWindow.setDefaultIcon(info.icon);
mWindow.setDefaultLogo(info.logo);
mActionBar = new WindowDecorActionBar(this);
}
WindowManager.LayoutParams l = mWindow.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
nl.copyFrom(l);
nl.softInputMode |=
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
l = nl;
}
try {
mWindowManager.addView(mDecor, l); //note3
mShowing = true;
sendShowMessage(); //note4
} finally {
}
}void dispatchOnCreate(Bundle savedInstanceState) {if (!mCreated) {onCreate(savedInstanceState);mCreated = true;}}protected void onCreate(Bundle savedInstanceState) { }
protected void onStart() {if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true);}
public void hide() {
if (mDecor != null) {
mDecor.setVisibility(View.GONE);
}
}@Override
public void dismiss() {
if (Looper.myLooper() == mHandler.getLooper()) {
dismissDialog();
} else {
mHandler.post(mDismissAction); //如果不是UI线程则将dismiss交给handler去处理
}
}
dismissDialog()@Dialog.class
void dismissDialog() {
if (mDecor == null || !mShowing) {
return;
}
if (mWindow.isDestroyed()) {
Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
return;
}
try {
mWindowManager.removeViewImmediate(mDecor); //从WindowManager中remove DecorView
} finally {
if (mActionMode != null) {
mActionMode.finish(); .//销毁ActionBar
}
mDecor = null;
mWindow.closeAllPanels();
onStop();
mShowing = false;
sendDismissMessage(); //触发dismiss监听器
}
}setContentView@Activity.classpublic void setContentView(@LayoutRes int layoutResID) {mWindow.setContentView(layoutResID);initWindowDecorActionBar(); //对ActionBar进行一些初始化}private Window mWindow = new PhoneWindow(this);可以发现跟这里的流程基本都是一样的,OnCreate中创建PhoneWindow然后得到Decorview,最后在onResume方法中将Decorview交给WindowManager去处理,其实最终是交给WindowManagerService进行管理,后者负责显示视图和传递用户的事件。
标签:
原文地址:http://blog.csdn.net/evan_man/article/details/51812678