Activity嵌入常在大屏设备上使用,当两个activity并排显示时,如果某一activity要弹窗,dialog会依附于该activity。
此时,dialog并不会在屏幕居中显示,而是在该activity居中,因为窗口类型为WindowManager.LayoutParams.TYPE_APPLICATION。如果我们要使dialog全屏居中,就要给dialog所在的窗口设置WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY类型。
当应用状态发生变化,如
由前台切换到后台,需要隐藏弹窗;
由后台切换到前台,需要显示弹窗;
由全屏模式切换到多窗口模式,此时activity通常会堆叠而不是并排显示,需要调整窗口类型;
由多窗口模式切换到全屏模式,此时activity通常会并排而不是堆叠显示,也需要调整窗口类型;
此时,我们需要对dialog进行封装,否则容易引起交互上的问题。
wrapActivityEmbeddedDialog
public static void wrapActivityEmbeddedDialog(Dialog dialog) {
wrapActivityEmbeddedDialog(dialog, null);
}
/**
* 请注意调用次方法的时机
* 需要在onPostCreate或者onResume中同步调用即可生效,如果在onCreate中调用,需要等readyRunnable回调之后在show dialog
* @param dialog
* @param readyRunnable 调用的时候如果Activity还不是resume状态则会等待监听onActivityResumed的时候回调
*/
public static void wrapActivityEmbeddedDialog(Dialog dialog, Runnable readyRunnable) {
if (dialog == null || dialog.getWindow() == null) {
return;
}
Activity hostActivity = findActivity(dialog.getContext());
if (hostActivity == null) {
return;
}
if (hostActivity.isResumed() || readyRunnable == null) {
Log.d(TAG, "wrapActivityEmbeddedDialog activity.isResumed()");
changeDialogWindowType(dialog, hostActivity, true);
return;
}
if (hostActivity instanceof AppCompatActivity) {
AppCompatActivity hostCompatActivity = (AppCompatActivity) hostActivity;
hostCompatActivity.getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) {
Log.d(TAG, "wrapActivityEmbeddedDialog onStateChanged: " + event.name() +
" className: " + hostCompatActivity.getLocalClassName() +
" activity: " + hostCompatActivity.hashCode());
if (event == Lifecycle.Event.ON_RESUME) {
changeDialogWindowType(dialog, hostActivity, true);
readyRunnable.run();
hostCompatActivity.getLifecycle().removeObserver(this);
}
}
});
}
}
changeDialogWindowType
private static void changeDialogWindowType(Dialog dialog, Activity activity, boolean isAddAutoShowHideStrategy) {
Window window = dialog.getWindow();
if (window == null) {
return;
}
try {
if (activity.isInMultiWindowMode()) {
window.setType(WindowManager.LayoutParams.TYPE_APPLICATION);
return;
}
if (isAddAutoShowHideStrategy) {
addAutoShowHideStrategy(dialog, activity);
}
window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
addAutoShowHideStrategy
private static void addAutoShowHideStrategy(Dialog dialog, Activity activity) {
if (activity instanceof AppCompatActivity) {
AppCompatActivity hostCompatActivity = (AppCompatActivity) activity;
hostCompatActivity.getLifecycle().addObserver(new LifecycleEventObserver() {
private boolean isShowBeforeStopped = false;
@Override
public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) {
Log.d(TAG, "changeDialogWindowType onStateChanged: " + event.name() +
" className: " + hostCompatActivity.getLocalClassName() +
" activity: " + hostCompatActivity.hashCode());
if (event == Lifecycle.Event.ON_START) {
if (isShowBeforeStopped) {
isShowBeforeStopped = false;
// Dialog重新恢复显示的时候,可能窗口模式发生了变化:比如从全屏模式变成小窗模式
changeDialogWindowType(dialog, activity, false);
dialog.show();
}
} else if (event == Lifecycle.Event.ON_STOP) {
isShowBeforeStopped = dialog.isShowing();
dialog.dismiss();
} else if (event == Lifecycle.Event.ON_DESTROY) {
dialog.dismiss();
hostCompatActivity.getLifecycle().removeObserver(this);
}
}
});
}
}
findActivity
public static Activity findActivity(@NonNull Context context) {
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
return findActivity(((ContextWrapper) context).getBaseContext());
} else {
return null;
}
}