您的位置:首页技术文章
文章详情页

Android 如何实现弹窗顺序&优先级控制

浏览:5日期:2022-09-20 09:06:29

一般在项目首页中,往往会有多个对话框需要弹出,比如活动弹窗、更新弹窗、评分弹窗等等,而且这些弹窗是有优先级顺序的。这些弹窗一般是通过接口请求后返回结果再显示的,如果只有几个弹窗还好处理,业务逻辑上判断一下先后显示就可以。如果有十几个或者更多,那么处理起来将非常麻烦,而且容易出现问题。

所以封装一个可以按照优先级顺序显示的弹窗功能就非常有必要,首先功能需求如下:

按优先级顺序阻塞式显示各种类型弹窗,默认从最高优先级开始显示 只有上一个高优先级弹窗显示完或者取消显示,下一个低优先级弹窗才可以显示 指定显示某一个弹窗的前提是没有更高优先级的弹窗需要显示 在显示一个弹窗之前需要判断是否能够或者需要显示 根据优先级去查找指定的弹窗,优先级相当于唯一ID 弹窗包括多种类型,Dialog、PopupWindow、Activity等等

接着开始编码去实现功能,先定一个枚举类,罗列出支持的弹窗类型,包括Dialog、PopupWindow、Activity等等。

public enum WindowType { DIALOG, POUPOWINDOW, TOAST, SNACKBAR, WIDGET, ACTIVITY, OTHERS}

然后定义弹窗接口IWindow,它定义了弹窗的基本功能。

/*** 窗口约定规则*/public interface IWindow { /** * 弹窗展示 */ void show(Activity activity); /** * 弹窗关闭 */ void dismiss(); /** * 设置窗口关闭监听 */ void setOnWindowDismissListener(OnWindowDismissListener listener); /** * 设置窗口展示监听 */ void setOnWindowShowListener(OnWindowShowListener listener);}

以及弹窗显示和关闭的监听接口,

/*** 窗口关闭监听*/public interface OnWindowDismissListener { /** * */ void onDismiss();}/*** 窗口展示监听*/public interface OnWindowShowListener { void onShow();}

接下来定义个包裹类WindowWrapper去封装弹窗相关的属性和状态,包括弹窗、优先级、能否显示、窗体类型等等,在处理弹窗显示逻辑时将会用到。

/*** 窗口参数类*/public class WindowWrapper { /** * 窗口 */ private IWindow mWindow; /** * 优先级,值越大优先级越高 */ private int mPriority; /** * 当前是否处于show状态 */ private boolean isShowing; /** * 是否满足show的条件 */ private boolean isCanShow; /** * 弹窗类型 */ private WindowType mWindowType; /** * 弹窗名称 */ private String mWindowName; private WindowWrapper(Builder builder) { mWindow = builder.window; mPriority = builder.priority; mWindowType = builder.windowType; isCanShow = builder.isCanShow; mWindowName = builder.windowName; } public IWindow getWindow() { return mWindow; } public void setWindow(IWindow window) { this.mWindow = window; } public int getPriority() { return mPriority; } public void setPriority(int priority) { this.mPriority = priority; } public boolean isShowing() { return isShowing; } public void setShowing(boolean showing) { isShowing = showing; } public WindowType getWindowType() { return mWindowType; } public void setWindowType(WindowType mWindowType) { this.mWindowType = mWindowType; } public boolean isCanShow() { return isCanShow; } public void setCanShow(boolean canShow) { isCanShow = canShow; } public String getWindowName() { return mWindowName; } public void setWindowName(String mWindowName) { this.mWindowName = mWindowName; } public static class Builder { /** * 窗口 */ private IWindow window; /** * 优先级,值越大优先级越高 */ private int priority; /** * 弹窗类型 */ private WindowType windowType; /** * 是否满足show的条件 */ private boolean isCanShow; /** * 弹窗名称 */ private String windowName; public Builder window(IWindow window) { this.window = window; return this; } public Builder priority(int priority) { this.priority = priority; return this; } public Builder windowType(WindowType type) { this.windowType = type; return this; } public Builder setCanShow(boolean canShow) { isCanShow = canShow; return this; } public String getWindowName() { return windowName; } public Builder setWindowName(String windowName) { this.windowName = windowName; return this; } public WindowWrapper build() { return new WindowWrapper(this); } }}

最后通过WindowTaskManager类去统一组织管理弹窗的添加、显示、关闭等逻辑,

public class WindowTaskManager { private List<WindowWrapper> mWindows; private static WindowTaskManager mDefaultInstance; private WindowTaskManager() { } /** * 获取弹窗管理者 */ public static WindowTaskManager getInstance() { if (mDefaultInstance == null) { synchronized (WindowTaskManager.class) {if (mDefaultInstance == null) { mDefaultInstance = new WindowTaskManager();} } } return mDefaultInstance; } /** * 添加弹窗 * * @param windowWrapper 待显示的弹窗 */ public synchronized void addWindow(Activity activity, WindowWrapper windowWrapper) { if (windowWrapper != null) { if (mWindows == null) {mWindows = new ArrayList<>(); } if (windowWrapper.getWindow() != null) {windowWrapper.getWindow().setOnWindowShowListener(new OnWindowShowListener() { @Override public void onShow() { windowWrapper.setShowing(true); }});windowWrapper.getWindow().setOnWindowDismissListener(new OnWindowDismissListener() { @Override public void onDismiss() { windowWrapper.setShowing(false); mWindows.remove(windowWrapper); showNext(activity); }}); } mWindows.add(windowWrapper); } } /** * 弹窗满足展示条件 * * @param priority */ public synchronized void enableWindow(Activity activity, int priority, IWindow window) { WindowWrapper windowWrapper = getTargetWindow(priority); if (windowWrapper != null) { if (windowWrapper.getWindow() == null) {window.setOnWindowShowListener(new OnWindowShowListener() { @Override public void onShow() { windowWrapper.setShowing(true); }});window.setOnWindowDismissListener(new OnWindowDismissListener() { @Override public void onDismiss() { windowWrapper.setShowing(false); mWindows.remove(windowWrapper); showNext(activity); }}); } windowWrapper.setCanShow(true); windowWrapper.setWindow(window); show(activity, priority); } } /** * 移除不需要显示弹窗 * * @param priority */ public synchronized void disableWindow(int priority) { WindowWrapper windowWrapper = getTargetWindow(priority); if (windowWrapper != null && windowWrapper.getWindow() != null) { if (mWindows != null) {mWindows.remove(windowWrapper); } } } /** * 展示弹窗 * 从优先级最高的Window开始显示 */ public synchronized void show(Activity activity) { WindowWrapper windowWrapper = getMaxPriorityWindow(); if (windowWrapper != null && windowWrapper.isCanShow()) { IWindow window = windowWrapper.getWindow(); if (window != null) {window.show(activity); } } } /** * 显示指定的弹窗 * * @param priorities */ public synchronized void show(Activity activity, int priorities) { WindowWrapper windowWrapper = getTargetWindow(priorities); if (windowWrapper != null && windowWrapper.getWindow() != null) { WindowWrapper topShowWindow = getShowingWindow(); if (topShowWindow == null) {int priority = windowWrapper.getPriority();WindowWrapper maxPriorityWindow = getMaxPriorityWindow();if (maxPriorityWindow != null && windowWrapper.isCanShow() && priority >= maxPriorityWindow.getPriority()) { if (windowWrapper.getWindow() != null) { windowWrapper.getWindow().show(activity); }} } } } /** * 清除弹窗管理者 */ public synchronized void clear() { if (mWindows != null) { for (int i = 0, size = mWindows.size(); i < size; i++) {if (mWindows.get(i) != null) { IWindow window = mWindows.get(i).getWindow(); if (window != null) { window.dismiss(); }} } mWindows.clear(); } WindowHelper.getInstance().onDestroy(); } /** * 清除弹窗管理者 * * @param dismiss 是否同时dismiss掉弹窗管理者维护的弹窗 */ public synchronized void clear(boolean dismiss) { if (mWindows != null) { if (dismiss) {for (int i = 0, size = mWindows.size(); i < size; i++) { if (mWindows.get(i) != null) { IWindow window = mWindows.get(i).getWindow(); if (window != null) { window.dismiss(); } }} } mWindows.clear(); } WindowHelper.getInstance().onDestroy(); } /** * 展示下一个优先级最大的Window */ private synchronized void showNext(Activity activity) { WindowWrapper windowWrapper = getMaxPriorityWindow(); if (windowWrapper != null && windowWrapper.isCanShow()) { if (windowWrapper.getWindow() != null) {windowWrapper.getWindow().show(activity); } } } /** * 获取当前栈中优先级最高的Window(优先级相同则返回后添加的弹窗) */ private synchronized WindowWrapper getMaxPriorityWindow() { if (mWindows != null) { int maxPriority = -1; int position = -1; for (int i = 0, size = mWindows.size(); i < size; i++) {WindowWrapper windowWrapper = mWindows.get(i);if (i == 0) { position = 0; maxPriority = windowWrapper.getPriority();} else { if (windowWrapper.getPriority() >= maxPriority) { position = i; maxPriority = windowWrapper.getPriority(); }} } if (position != -1) {return mWindows.get(position); } else {return null; } } return null; } private synchronized WindowWrapper getTargetWindow(int priority) { if (mWindows != null) { for (int i = 0, size = mWindows.size(); i < size; i++) {WindowWrapper windowWrapper = mWindows.get(i);if (windowWrapper != null && windowWrapper.getPriority() == priority) { return windowWrapper;} } } return null; } /** * 获取当前处于show状态的弹窗 */ private synchronized WindowWrapper getShowingWindow() { if (mWindows != null) { for (int i = 0, size = mWindows.size(); i < size; i++) {WindowWrapper windowWrapper = mWindows.get(i);if (windowWrapper != null && windowWrapper.getWindow() != null && windowWrapper.isShowing()) { return windowWrapper;} } } return null; }}

WindowTaskManager类有三个主要方法:

addWindow(Activity activity, WindowWrapper windowWrapper) enableWindow(Activity activity, int priority, IWindow window) disableWindow(int priority)

需要按顺序显示的对话框统一使用addWindow方法添加,这是还未进行网络请求之前就要调用的。作用是告诉WindowTaskManager一共有多少个弹窗需要按顺序显示。当网络请求返回之后,如果需要显示弹窗就调用enableWindow方法去显示,如果不需要显示弹窗就调用disableWindow方法,将这个弹窗从显示队列中移除。

以上就是按顺序显示弹窗的主要逻辑,使用的话窗体先继承IWindow,实现相关方法。然后通过操作WindowTaskManager类就可以了。具体使用方法参见源码。

项目地址:github.com/Geekince/Pr…

彩蛋:

需要在DialogFragment中显示DialogFragment时候,最好不要直接在DialogFragment启动显示,而是在DialogFragment的消失回调中启动显示。因为当前一个DialogFragment消失的时候,getChildFragmentManager可能会失效,应该在外层使用getFragmentManager。

以上就是Android 如何实现弹窗顺序&优先级控制的详细内容,更多关于Android 实现弹窗顺序和优先级控制的资料请关注好吧啦网其它相关文章!

标签: Android
相关文章: