看源码:
/**
* Sets whether this dialog is cancelable with the
* {@link KeyEvent#KEYCODE_BACK BACK} key. //点击物理返回键是否可取消dialog
*/
public void setCancelable(boolean flag) {
mCancelable = flag;
}
/**
* Sets whether this dialog is canceled when touched outside the window's
* bounds. If setting to true, the dialog is set to be cancelable if not
* already set.
*
* @param cancel Whether the dialog should be canceled when touched outside
* the window. //点击dialog之外 是否可取消
*/
public void setCanceledOnTouchOutside(boolean cancel) {
if (cancel && !mCancelable) {
mCancelable = true;
}
mWindow.setCloseOnTouchOutside(cancel);
}
/**
* Cancel the dialog. This is essentially the same as calling {@link #dismiss()}, but it will
* also call your {@link DialogInterface.OnCancelListener} (if registered).
* // 取消dialog ,和dismiss相同,但cancel会回调DialogInterface.OnCancelListener
*/
@Override
public void cancel() {
if (!mCanceled && mCancelMessage != null) {
mCanceled = true;
// Obtain a new message so this dialog can be re-used
Message.obtain(mCancelMessage).sendToTarget();
}
dismiss();
}
/**
* Set a listener to be invoked when the dialog is canceled. //设置监听取消dialog
*
* <p>This will only be invoked when the dialog is canceled.
* Cancel events alone will not capture all ways that
* the dialog might be dismissed. If the creator needs
* to know when a dialog is dismissed in general, use
* {@link #setOnDismissListener}.</p>
*
* @param listener The {@link DialogInterface.OnCancelListener} to use.
*/
public void setOnCancelListener(@Nullable 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;
}
}
/**
* Hide the dialog, but do not dismiss it. //隐藏dialog(设置为Gone),但是不dismiss
* //hide只是把对话框里的DecorView设置为不可见,并没有从Window移除掉这个DecorView。
*/
public void hide() {
if (mDecor != null) {
mDecor.setVisibility(View.GONE);
}
}
/**
* Dismiss this dialog, removing it from the screen. This method can be
* invoked safely from any thread. Note that you should not override this
* method to do cleanup when the dialog is dismissed, instead implement
* that in {@link #onStop}. //从屏幕移除,可以任意线程使用,在onstop中移除
* //dismiss可以在任何线程调用,但是最好不要覆写dismiss方法,实在需要就在onStop里去dismiss。
*/
@Override
public void dismiss() {
if (Looper.myLooper() == mHandler.getLooper()) {
dismissDialog();
} else {
mHandler.post(mDismissAction);
}
}
dismiss、cancel和hide区别
dismiss、cancel两者效果都是一样的,其实看下源码就知道cancel肯定会去调dismiss的,如果调用的cancel的话就可以监听DialogInterface.OnCancelListener。
hide只是隐藏了对话框并没有销毁,如果打算用这方法来灭掉对话框就会出现问题,在Activity销毁的时候就会出现崩溃日志了,因为Activity销毁时是需要把对话框都关闭掉的。
setCancelable与setCanceledOnTouchOutside的区别
setCancelable : 点击物理返回键是否可关闭弹框
setCanceledOnTouchOutside: 点击弹框外 是否可关闭弹框
异常:
not attached to window manager
解决:
ondestroy中要关闭dialog:
@Override
protected void onDestroy() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
super.onDestroy();
}
示例如下:
public class TestActivity extends AppCompatActivity {
private Dialog progressDialog;
@Override
protected void onPause() {
super.onPause();
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
@Override
protected void onDestroy() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog = null;
super.onDestroy();
}
protected void showLoading() {
if (progressDialog == null) {
progressDialog = new Dialog(this, R.style.progress_dialog);
}
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog.setContentView(R.layout.logindialog);
progressDialog.setCancelable(true);
progressDialog.setCanceledOnTouchOutside(false);
Window window = progressDialog.getWindow();
if (window != null) {
window.setBackgroundDrawableResource(android.R.color.transparent);
}
progressDialog.show();
}
protected void dismissLoading() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}