Activity嵌入场景下封装dialog弹窗

1 阅读2分钟

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;
    }
}