考拉Android统一弹框

作者:钱成杰

背景

在快速开发的背景下,经历了n个版本后的考拉Android App中已经存在了各种各样看似相同却各有差别的弹框样式。其中包括系统弹框和自定义弹框,并且在线上时常会出现IllegalArgumentException的异常,而现有的解决方法是通过工具类来保护调用show和dismiss方法,这种方式效率不高,而且覆盖不全,开发过程中容易遗漏。另外现有的Builder方式的弹框构造工具虽然功能强大,能构造各种弹框,但是使用复杂,样式逻辑耦合,使用成本太高。于是,便需要一款样式统一、show和dismiss安全、调用简单、构造方便的统一弹框工具。

目标

  1. 统一弹框的交互样式
  2. show和dismiss方法安全
  3. 样式与逻辑解耦,使用者不必关心弹框样式,只需要完成自己的续逻辑即可
  4. 使用简单,一个接口即可获得所需样式
  5. 扩展性,可支持展示特别样式弹框

怎么做?

既然有了特定的目标,那么就要开始弹框的设计了。弹框通过工厂模式设计生产,使用者通过CommonDialogFactory提供的接口,可以直接生产CommonDialog类、KaolaCommonDialog类、KaolaBottomCloseDialog类三种弹框,其中CommonDialog是为了兼容旧逻辑保留的旧的弹框样式,KaolaCommonDialog是新设计统一了样式的弹框类,但是两者在样式上没有很大的区别,KaolaBottomCloseDialog是一种底部关闭的弹框样式。

0. 保留CommonDialog的旧的构建方式。

考虑到旧的弹框中有不少弹框的业务逻辑与旧的Builder工具样式有耦合,为了保证业务逻辑不受影响,我保留了以前的Builder方式构造弹框的设计,并且对其进行了接口化封装。这样可以降低构造弹框的成本。

1. 整理目前项目中用到的弹框的样式。

由于不熟悉别的模块中弹框到底有哪些样式,所以需要整理目前项目中所有用到的弹框样式。统计结果发现大部分弹框使用的是系统弹框,而自定义弹框中不少样式已经不再使用,但是在旧的构造工具中依然存在,由于逻辑耦合,后期维护相对麻烦,这也验证了我们统一弹框组件的必要性。

2. 慢慢从DialogManager里面把样式抽出来,形成基本样式。

从旧的弹框管理类DialogManager中,将现在正在使用的弹框抽离出来,在弹框工厂CommonDialogFactory中封装成单独的接口以提供使用。也可以根据整理的接口,形成一套基本的弹框样式,这样在后面做样式统一的时候就可以参考着现有的样式去做了。

3. 具体弹框样式形成文档维护在wiki上(提供使用帮助)。

那么为了更方便地使用和维护统一弹框组件,使用文档是必不可少的。把现有的弹框样式总结在wiki文档中,对于现有可用的弹框样式也是一目了然;还可以根据文档中提供的案例进行调用开发,降低成本。

4. 样式全部抽出来之后,那就按照统一的交互进行修正。

由于目前没有视觉提供的统一样式,所以我们基于第2点钟抽离出来的基本样式,按照这些样式来做构建的统一。然后再按照后续设计提供的统一交互规范进行进一步的修正,慢慢做到样式也统一,最后真正实现弹框的完全统一。

样式

下图中可以看到弹框类的继承关系:

KaolaBaseDialog中实现了安全的show和dismiss方法:

@Overridepublic void show() {    if (!checkAllow()) {        return;
    }    // 防止check无效
    try {        super.show();
    } catch (Exception e) {
        e.printStackTrace();
    }
}@Overridepublic void dismiss() {    if (mOnDismissListener != null) {
        mOnDismissListener.onDismiss(mDismissType);
    }    if (!checkAllow()) {        return;
    }    try {        super.dismiss();
    } catch (Exception e) {
        e.printStackTrace();
    }
}/**
 * 检查环境是否允许
 *
 * @return
 */private boolean checkAllow() {
    Context context = this.getContext();    if (context instanceof Lifeful) {
        Lifeful lifeful = (Lifeful) context;        if (!lifeful.isAlive()) {            return false;
        }
    } else if (context instanceof Activity) {        if (!ActivityUtils.activityIsAlive(context)) {            return false;
        }
    }    return true;
}

KaolaCommonDialog是通用样式类:

KaolaBottomDialog是底部弹出浮层:

KaolaBottomConfirmDialog是底部确认浮层:

KaolaBottomCloseDialog是底部带关闭弹框:

ExpectPickUpTimeDialog是时间选择器浮层:

通用弹框的文案也支持SpannableString的多样展示;另外可以看到KaolaBaseDialog可以使用在各种情况下,不仅仅是通用弹框,还可以是一些通用组件比如ExpectPickUpTimeDialog时间选择器(不过这里做成了与取件业务相关的组件)。

怎么用?

KaolaCommonDialog的使用

直接调用CommonDialogFactory提供的createOneOrTwoButtonsCustomView接口,该接口可以提供标题、文案、自定义view、通用按钮的展示,使用者可以通过wiki文档或者直接查看接口注释了解接口内容。

/**
 * 一个标题,一个文案,一个view,一个白底红字negative(left)按钮,一个红底白字positive(right)按钮
 *
 * @param context
 * @param title 标题,传空不带标题
 * @param message 提示文案
 * @param view 自定义区域需要添加的view
 * @param leftBtn 左边按钮的内容(传空不显示按钮)
 * @param rightBtn 右边按钮的内容(传空不显示按钮)
 * @return KaolaCommonDialog
 */public KaolaCommonDialog createOneOrTwoButtonsWithCustomView(Context context, String title, CharSequence message,
        View view, String leftBtn, String rightBtn) {
            ...
        }

KaolaCommonDialog dialog = CommonDialogFactory.getInstance()
        .createOneOrTwoButtonsWithCustomView(this, "标题", "提示文案", getCustomView(), "取消", "确定")
        .setOnLeftButtonClickListener(() -> ToastUtils.show("leftClick... negative"))
        .setOnRightButtonClickListener(() -> ToastUtils.show("rightClick... positive"))
        .setCancelableOutside(true);
dialog.setOnDialogDismissListener(dismissType -> {    // dismiss回调
    ThreadCore.getInstance().postOnMainLooper(new LifefulRunnable(new Runnable() {        @Override
        public void run() {            if (dismissType == KaolaBaseDialog.DISMISS_TYPE_POSITIVE) {
                ToastUtils.show("右侧按钮点击消失");
            } else if (dismissType == KaolaBaseDialog.DISMISS_TYPE_NEGATIVE) {
                ToastUtils.show("左侧按钮点击消失");
            } else {
                ToastUtils.show("其他消失");
            }
        }
    }, DialogTestActivity.this), 1000);
});// 不展示顶部分割线dialog.dividerTop.setVisibility(View.GONE);
dialog.show();

考虑到一些特殊情况的需求,默认的样式无法满足视觉要求的时候,就需要定制化一些弹框中的内容了。所以弹框类中的各个成员以public的形式开发给使用者,以适应各种定制化要求,比如:不希望展示title下面的分割线,可以直接获取dividerTop对象进行设置。另外自定义view参数可以满足对弹框内容的特殊化定制。在统一了弹框调用之后,依然具有很强的扩展性。

KaolaBottomDialog的使用

考虑到底部浮层的多样性,没有将KaolaBottomDialog的构建放入CommonDialogFactory中,而是使用通用的构建方式构建。

private KaolaBottomDialog chooseDialog;
...
chooseDialog = new KaolaBottomDialog(this);// 展示浮层右上角关闭按钮chooseDialog.showRightClose(true);
...// 设置标题(String)和内容(ListView)chooseDialog.setContent(getString(R.string.refund_delivery), dialogListView)            // 限制浮层最大屏高比(最大为屏幕高度的2/3)
            .setDialogHeight(2f / 3);
chooseDialog.show();

思考

统一交互既能够给产品带来更好体验,又可以减少开发者不必要的开发工作,降低代码耦合,提高工作效率,是一个建议并值得去做的事情。目前的统一弹框方案还是有很多不足,等着我们去优化,比如将所有Dialog统一到CommonDialogFactory中去构建,再使用等等。

网易云产品免费体验馆,无套路试用,零成本体验云计算价值。

本文来自网易实践者社区,经作者钱成杰授权发布

更多网易研发、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 SpringBoot入门(四)——自动配置
【推荐】 SpringFox 初体验
【推荐】 Lily-一个埋点管理工具

原文地址:https://www.cnblogs.com/163yun/p/9662157.html

时间: 2024-08-26 01:20:18

考拉Android统一弹框的相关文章

网易考拉Android客户端网络模块设计

本文来自网易云社区 作者:王鲁才 客户端开发中不可避免的需要接触到访问网络的需求,如何把访问网络模块设计的更具有扩展性是每一个移动开发者不得不面对的事情.现在有很多主流的网络请求处理框架,如Square公司的OkHttp,Google推出的Volley,还有在OkHttp基础上进行封装的Retrofit等,这些都是非常优秀的网络处理框架.利用现有网络处理框架,比从零开始设计.开发网络请求节省很多开发时间,同时也避免了一些意想不到的问题.如果把这些框架直接拿来使用,不进行任何二次封装,会使我们工程

android 系统弹框不消失

AlertDialog.Builder builder = new AlertDialog.Builder(_context); builder.setTitle("温馨提示").setMessage("您的账户被锁定,请联系闭门!") .setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialo

点击按钮弹框显示ListView,点击ListView某一项做出相应

最近在做上面描述的功能,网上找了个几个例子,拼拼凑凑整出来了效果,首先多谢http://www.cnblogs.com/miya2012/archive/2012/08/23/2652224.html,  代码实现差不多,特地做了个例子.附在最后? 不多说,先看效果图哈.      好了,上代码 MainActivity.java public class MainActivity extends Activity { private Button btn; private List<Strin

android如果给TextView或EditText的email链接加下划线,并在点击在email连接上可以弹框显示

如何把textview的一些文字加上背景色: Spannable str = new SpannableString("#fdsfdfsdfdsfd#"); Matcher matcher = getEmailPattern().matcher((CharSequence) str); while (matcher.find()) { int start = matcher.start(); int end = matcher.end(); str.setSpan(new Foregr

Android的弹出登陆框的实现

最近在做一个项目,要用到登陆框,几经波折,最后用的是直接将Activity的Theme属性设置成Dialog,然后达到了我想要的效果. 下面是我的实现经历: 1.首先,我是直接使用AlertDialog来实现,确定是,形状有点难看,而且获得Dialog里面的控件略显麻烦(因为我要做的登陆框有一定的布局),然后就给我就放弃了,可能因为我太水了,不能很好的使用它 2.然后我就使用PopupWindow来实现,界面是达到了我的要求,控件的获得通过Inflater就可以获得了相对较简单,但是有一个缺点就

驾考网上理论刷学时防每20分钟弹框

福建省驾考网上理论自动刷学时.考驾照时,都要到学时管理系统上刷学时,科目二2个小时,科目三16个小时,每次刷学时时超过20分钟没反应就会被迫终止.这对有些人来说可能没有那么多空闲的时间,为了解决每20分钟弹窗问题,提供下面方法. 1.进入科二或科三理论学习页面,鼠标右击,点击“检查”选项或者“审查元素”(不同浏览器不同)如下:点击完后会出现下面窗口,选择“console”菜单栏 将以下代码复制黏贴到console中,回车 科二: var action = function(){ShowNumbe

Android版的SweetAlert,清新文艺,快意灵动的甜心弹框

Android版的SweetAlert,清新文艺,快意灵动的甜心弹框 使用服务:其他        功能分类:其他     支持平台:Android 运行环境:Eclipse    开发语言:Java     开发工具:Eclipse 下载地址:http://sina.lt/zVe 源码简介 Android版的SweetAlert,清新文艺,快意灵动的甜心弹框,使用Eclipse导入即可! 运行动态图

Android 底部弹出提示框的解决办法(使用Activity以及PopupWindow)

本片文章主要谈探讨了如何实现在底部弹出提示框背景为半透明效果的实现.想要实现此种效果一般有两种方式一个是使用Activity设置Theme另一种方式就是使用PopupWindow设置样式实现效果. 一,使用Activity 首先是此activity的布局文件: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.andro

Android底部弹出iOS7风格对话选项框

<Android底部弹出iOS7风格对话选项框> 效果图如下: 网上流传的Android底部弹出iOS7风格的对话选项框开源代码,原作者不详.我在网上流传的代码基础上改进了一些地方,把原来作为Application发布的代码整理成一个Android的Library,如果在未来的Android项目中需要这样的对话选项框样式,则只需要下载我上次到CSDN的完整库项目(完整的Android库项目代码我已经上传到CSDN,下载地址:http://download.csdn.net/download/z