精华内容
下载资源
问答
  • Android自定义弹窗
    2021-05-26 13:41:40

    记录一下自定义的一个弹窗工具,代码中还有很多待优化的地方,例如样式自定义等,按钮布局等,都是可以优化的地方,还有我这个弹窗按钮上限是三个,也可以显示列表,当然没有一些完善的第三方开源库这么好,但是在没有那么复杂多变的情况下是够用的了

    /**

    * 显示弹窗,不可点击外部取消,可根据传入按钮名称列表显示不同数目的按钮,最多三个

    * @param activity 当前页面

    * @param message 显示内容

    * @param listener 监听点击处理,根据

    * @param buttonName 按钮显示的文本,最大值为三个

    * @param title 标题

    */

    public static void showDialog(Activity activity,String message,final DialogListener listener,String[] buttonName,String title)

    /**

    * 显示弹窗,可点击外部取消,可根据传入按钮名称列表显示不同数目的按钮,最多三个

    * @param activity 当前页面

    * @param message 显示内容

    * @param listener 监听点击处理,根据

    * @param buttonName 按钮显示的文本,最大值为三个

    * @param title 标题

    */

    public static void showDialogCanOutThouch(Activity activity,String message,final DialogListener listener,String[] buttonName,String title)

    /**

    * 显示列表弹窗,默认为一个取消按钮,可点击外部关闭

    * @param activity 当前页面

    * @param items 列表数组

    * @param title 标题

    * @param itemClick 点击监听处理

    */

    public static void showDialogWithItems(Activity activity,String[] items,String title, OnItemClickListener itemClick)

    /**

    * 显示列表弹窗,默认为一个取消按钮,不可点击外部关闭

    * @param activity 当前页面

    * @param items 列表数组

    * @param title 标题

    * @param itemClick 点击监听处理

    */

    public static void showDialogJustClickItems(Activity activity,String[] items,String title, OnItemClickListener itemClick)

    /**

    * 只显示消息的弹窗,按钮无功能,默认为一个确定按钮,从页面弹起的窗口

    * @param activity 当前页面

    * @param message 消息

    */

    public static void justShowMessage(Activity activity,String message)

    /**

    * 只显示消息的弹窗,按钮无功能,默认为一个确定按钮,从工具类或控件获取的context弹起的窗口

    * @param activity 当前页面

    * @param message 消息

    */

    public static void justShowMessage(Context activity,String message)

    /**

    * 只显示消息的弹窗,按钮无功能,默认为一个确定按钮,从工具类或控件获取的context弹起的窗口

    * @param activity 当前页面

    * @param message 消息

    * @param title 标题

    */

    public static void justShowMessage(Context activity,String message,String title)

    效果

    a709d654e066?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    TIM图片20190305205855.gif

    更多相关内容
  • 获取用户的信息授权弹窗,更改内容的方法  小程序发布前,发现获取用户信息的地方是这样的, (此图片来源于网络,如有侵权,请联系删除! )  然后发现别人的是这样的 (此图片来源于网络,如有侵权,请联系删除! ) ...
  • Android:实现弹窗效果

    千次阅读 2022-03-22 16:25:20
    Android:dialog

    效果展示

    UI设计想让我实现这样一个弹窗效果,点击中部+号,可以出现一个弹窗,同时可供进一步跳转。
    先看最后完成的效果。
    请添加图片描述

    为了实现这个效果,主要拆解成几个部分:弹窗绘制、弹窗逻辑编写、弹窗动画

    弹窗绘制

    首先绘制三个弹窗中的按钮形状
    button_circle3.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <!-- 填充的颜色 -->
        <solid android:color="@color/bar" />
        <corners
            android:radius="25dip" />
    </shape>
    

    之后,构建弹窗文件主体
    diglog_j.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/dialog_bk"
        android:orientation="vertical"
        android:layout_marginLeft="50dp"
        android:layout_marginRight="50dp">
    
        <Button
            android:id="@+id/btn_fabu"
            android:layout_width="180dp"
            android:layout_height="wrap_content"
            android:background="@drawable/button_circle3"
            android:gravity="center"
            android:text="发布商品"
            android:textStyle="bold"
            android:textColor="@color/white"
            android:textSize="22sp"
            android:layout_marginRight="32dp"
            android:layout_marginLeft="32dp"
            android:layout_marginTop="50dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_gravity="center"/>
    
        <Button
            android:id="@+id/btn_dingzhi"
            android:layout_width="180dp"
            android:layout_height="wrap_content"
            android:background="@drawable/button_circle3"
            android:gravity="center"
            android:text="定制方案"
            android:textStyle="bold"
            android:textColor="@color/white"
            android:textSize="22sp"
            android:layout_marginRight="32dp"
            android:layout_marginLeft="32dp"
            android:layout_marginTop="30dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_gravity="center"/>
    
    
        <Button
            android:id="@+id/btn_renling"
            android:layout_width="180dp"
            android:layout_height="wrap_content"
            android:background="@drawable/button_circle3"
            android:gravity="center"
            android:text="认领小羊"
            android:textStyle="bold"
            android:textColor="@color/white"
            android:textSize="22sp"
            android:layout_marginRight="32dp"
            android:layout_marginLeft="32dp"
            android:layout_marginTop="30dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_gravity="center"
            android:layout_marginBottom="50dp"/>
    </LinearLayout>
    

    最后绘制弹窗框的形状
    dialog_bk.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <layer-list>
                <!-- SHADOW LAYER -->
                <item android:top="4dp">
                    <shape>
                        <solid android:color="@color/black" />
                        <corners android:radius="30dip"/>
                    </shape>
    
                </item>
                <!-- CONTENT LAYER -->
                <item android:top="12dp">
                    <shape>
                        <solid android:color="@color/white" />
                        <corners
                            android:topLeftRadius="20dp"
                            android:topRightRadius="20dp" />
                        <stroke
                            android:width="1dp"
                            android:color="@color/me_blue"
                            />
                    </shape>
    
                </item>
            </layer-list>
        </item>
    </selector>
    

    这里比较巧妙的是绘制弹窗框的顶部阴影,使用了两层shape,让第一层往下偏移,实现阴影效果。
    再勾勒1dp的蓝色边框,使用stroke关键字

    至此,弹窗绘制完成。

    弹窗逻辑

    弹窗逻辑包含两个部分,一个是弹出逻辑,这部分Dialog已经做了足够的封装,调用相关API即可。另一个是弹窗内按钮的监听和跳转。
    这两部分统一写在show_dialog函数中。

    private void show_dialog(){
            dialog = new Dialog(this, R.style.ActionSheetDialogStyle);
            //填充对话框的布局
            inflate = LayoutInflater.from(this).inflate(R.layout.dialog_j, null);
            //获取控件
            Button btn_fabu = inflate.findViewById(R.id.btn_fabu);//取消
            Button btn_dingzhi = inflate.findViewById(R.id.btn_dingzhi);//支付宝支付
            Button btn_renling = inflate.findViewById(R.id.btn_renling);//添加银行卡
            //将布局设置给Dialog
            dialog.setContentView(inflate);
            //获取当前Activity所在的窗体
            Window dialogWindow = dialog.getWindow();
            //设置Dialog从窗体底部弹出
            dialogWindow.setGravity(Gravity.BOTTOM);
            //获得窗体的属性
            WindowManager.LayoutParams lp = dialogWindow.getAttributes();
            lp.y = 0;//设置Dialog距离底部的距离
            //宽度填充当前布局文件宽度
            lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
            //将属性设置给窗体
            dialogWindow.setAttributes(lp);
            dialog.show();//显示对话框
    
            btn_fabu.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent i = new Intent(MainActivity.this, fabushangpin.class);
                    startActivity(i);
                }
            });
    
            btn_dingzhi.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent i = new Intent(MainActivity.this, dingzhi.class);
                    startActivity(i);
                }
            });
    
            btn_renling.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent i = new Intent(MainActivity.this, renling.class);
                    startActivity(i);
                }
            });
        }
    

    弹窗动画

    弹窗动画包括两部分,一个是弹窗的效果,即后面的背景变暗;另一个是从下到上的弹出效果。
    在上面的函数中,引用了 R.style.ActionSheetDialogStyle,该文件就包含弹窗效果。

    在themes.xml中添加

      <style name="ActionSheetDialogStyle" parent="@android:style/Theme.Dialog">
            <!-- 背景透明 -->
            <item name="android:windowBackground">@android:color/transparent</item>
            <item name="android:windowContentOverlay">@null</item>
            <!-- 浮于Activity之上 -->
            <item name="android:windowIsFloating">true</item>
            <!-- 边框 -->
            <item name="android:windowFrame">@null</item>
            <!-- Dialog以外的区域模糊效果 -->
            <item name="android:backgroundDimEnabled">true</item>
            <!-- 无标题 -->
            <item name="android:windowNoTitle">true</item>
            <!-- 半透明 -->
            <item name="android:windowIsTranslucent">true</item>
            <!-- Dialog进入及退出动画 -->
            <item name="android:windowAnimationStyle">@style/ActionSheetDialogAnimation</item>
        </style>
        <!-- ActionSheet进出动画 -->
        <style name="ActionSheetDialogAnimation" parent="@android:style/Animation.Dialog">
            <item name="android:windowEnterAnimation">@anim/actionsheet_dialog_in</item>
            <item name="android:windowExitAnimation">@anim/actionsheet_dialog_out</item>
        </style>
    

    进出动画
    actionsheet_dialog_in.xml

    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="200"
        android:fromYDelta="100%"
        android:toYDelta="0" />
    

    actionsheet_dialog_out.xml

    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="200"
        android:fromYDelta="0"
        android:toYDelta="100%" />
    

    至此,效果完成。

    参考资料

    https://blog.csdn.net/juer2017/article/details/79012028

    展开全文
  • 以微信登录界面的toast弹窗为例: 我的appium版本是1.17.1,服务器运行时日志有这样的打印信息 所以我的desired_caps如下(如果是之前的版本,需要安装uiautomator2,并且在初始化时指定automationName为...

    在这里插入图片描述
    以微信登录界面的toast弹窗为例:

    我的appium版本是1.17.1,服务器运行时日志有这样的打印信息

    在这里插入图片描述
    所以我的desired_caps如下(如果是之前的版本,需要安装uiautomator2,并且在初始化时指定automationName为uiautomator2):

    desired_caps_a = {'platformName': "Android",
                          'platFormVersion': "10",
                          'deviceName': "dd",
                          'udid': "648d4f29",
                          'automationName': "UiAutomator2",
                          'noReset': False,
                          'unicodeKeyboard': True,
                          'resetKeyboard': True,
                          'appPackage': "com.tencent.mm",
                          'appActivity': "com.tencent.mm.ui.LauncherUI",
                          'autoGrantPermissions': True,
                          'chromedriverExecutable': r"C:\Users\v_yddchen\Desktop\chromedriver_win32 77.0\chromedriver.exe",
                          'chromeOptions': {'androidProcess': "com.tencent.mm:toolsmp"}  # webview的进程名字,不然会报错
        }
    

    填写登录信息,获取toast(有时来不及获取登录界面的toast信息,会拿到登录成功后,加载数据的toast):

    device_a = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps_a)
        my_logging = output_log(logging.DEBUG)
    # toast弹窗处理
        device_a.find_element_by_android_uiautomator('new UiSelector().text("登录")').click()
        time.sleep(1)
        device_a.find_element_by_android_uiautomator('new UiSelector().textContains("用微信号")').click()
        time.sleep(1)
        username_input = device_a.find_element_by_android_uiautomator('new UiSelector().textContains("请填写微信号")')
        username_input.clear()
        username_input.send_keys('xxx')
        pwd_input = device_a.find_element_by_android_uiautomator('new UiSelector().textContains("请填写密码")')
        pwd_input.clear()
        pwd_input.send_keys('xxx')
        device_a.find_element_by_android_uiautomator('new UiSelector().text("登录")').click()
        toast_el = WebDriverWait(device_a, 5, 0.00001).\
            until(lambda x: x.find_element_by_xpath("//*[contains(@text,'正在')]"))
        # toast_el = WebDriverWait(device_a, 5, 0.000001).\
        #     until(lambda x: x.find_element_by_xpath('//*[@class="android.widget.Toast"]'))
        print(toast_el.text)
        device_a.quit()
    

    当密码填写信息错误时,不管改定时器的间隔为多小,都找不到toast,比较奇怪。如果点击【登录】–登录完成,跳转,这个过程很短,也有可能获取不到toast。

    看完点赞 ~养成好习惯,以上内容希望对你有帮助,如果对软件测试、接口测试、自动化测试、面试经验交流感兴趣可以加入我们。642830685,免费领取最新软件测试大厂面试资料和Python自动化、接口、框架搭建学习资料!技术大牛解惑答疑,同行一起交流。

    展开全文
  • Android弹窗优先级管理高级应用

    千次阅读 2021-11-20 11:42:18
    之前我写过一篇Android优雅实现弹窗优先级管理来介绍如何在android日常开发中管理多个弹窗的优先级,这个解决方案也被其他开发者所采用,在这里也感谢大家的认可。 我们常说世界上唯一不变的就是变化,开发的业务...

    先看接入步骤:
    Step 1. Add the JitPack repository to your build file
    Add it in your root build.gradle at the end of repositories:

     allprojects {
    		repositories {
    			...
    			maven { url 'https://jitpack.io' }
    		}
    	}
    

    Step 2. Add the dependency

      dependencies {
    	        implementation 'com.github.linpeixu:DialogManager:1.0.0'
                //或者implementation'com.gitlab.linpeixu:dialogmanager:1.0.0'
    	}
    

    工程地址:https://github.com/linpeixu/DialogManager
    更新说明:https://github.com/linpeixu/DialogManager/releases
    工程地址:https://gitlab.com/linpeixu/dialogmanager
    更新说明:https://gitlab.com/linpeixu/dialogmanager/-/releases

    背景:

    之前我写过一篇Android优雅实现弹窗优先级管理来介绍如何在android日常开发中管理多个弹窗的优先级,这个解决方案也被其他开发者所采用,在这里也感谢大家的认可。

    在这里插入图片描述

    我们常说世界上唯一不变的就是变化,开发的业务场景也在不停地变化,所以之前的弹窗管理解决方案在某些业务上则有场景的限制了,比如Android优雅实现弹窗优先级管理更偏向于将各个自定义的Dialog(api上的Dialog)纳入管理,且每个Dialog需要实现我们约定好的“Dialog Interface”,这样的话某种意义上已经对自定义Dialog构成代码的入侵了,再比如我们的DialogActivity也是可以实现Dialog的效果的,业务上的需要有时候需要我们使用DialogActivity来完成弹窗的业务,这个时候其实我们所说的“弹窗”的概念已经需要包括Dialog和Activity等不同组件了,由此我在思考,能不能有一种通用上的“弹窗”概念,而不仅仅局限于日常的自定义的Dialog,且不要对我们需要被管理的“弹窗”有任何代码上的入侵。

    想法是美好的,开始行动,最终我重新封装了DialogManager,先看使用实例。

    这里我们为了说明“弹窗”只是一个概念,需要纳入优先级管理的class不限制具体的类型,我们使用这几种不同“概念”的弹窗来看看怎么应用,例如自定义MessageDialog(继承Dialog)、AlertDialog、以及String类型的“弹窗”。

    首先把对应的“概念”弹窗纳入管理只需要调用

    DialogManager.getInstance().add(Config<Type> config);
    

    在需要展示弹窗的时候只需要调用

    DialogManager.getInstance().show();
    

    接下来我们看看上边提到的三种“概念”弹窗是怎么纳入优先级管理的

    MessageDialog“概念”弹窗的配置

    DialogManager.Config<MessageDialog> config1= new DialogManager
                    .Config
                    .Builder<MessageDialog>()
                    .as(new DialogManager.BaseType<MessageDialog>(new MessageDialog(context, "第一个弹窗")) {
                        @Override
                        void init(DialogManager.Config<MessageDialog> config) {
                            config.getBaseType().getType().setOnDismissListener(new DialogInterface.OnDismissListener() {
                                @Override
                                public void onDismiss(DialogInterface dialog) {
                                   /*需要记住,在合适的地方一定要调用方法config.dispatch()通知DialogManager
                                   *接着展示下个“概念”弹窗
                                   */
                                    config.dispatch();
                                }
                            });
                        }
    
                        @Override
                        void show(DialogManager.Config<MessageDialog> config) {
                           /*这是DialogManager执行到展示“概念”弹窗的逻辑,需外部实现相应的show逻辑*/
                            config.getBaseType().getType().show();
                        }
    
                        @Override
                        void dismiss(DialogManager.Config<MessageDialog> config) {
                           /*这是DialogManager执行到隐藏“概念”弹窗的逻辑,需外部实现相应的dismiss逻辑*/
                            config.getBaseType().getType().dismiss();
                        }
                    })
                    .priority(1)
                    .onShowCheckListener(new DialogManager.OnShowCheckListener() {
                        @Override
                        public boolean isCanShow() {
                           /*这是告诉DialogManager此“概念”弹窗可否展示*/
                           /*如我们有些业务需要首页处于哪个Tab时才可展示此弹窗
                            *可以在这里自行实现判断条件
                           */
                            return true;
                        }
                    })
                    .build();
    

    String“概念”弹窗的配置

    DialogManager.Config<String> config2 = new DialogManager
                    .Config
                    .Builder<String>()
                    .as(new DialogManager.BaseType<String>("这是个文字") {
                        @Override
                        void init(DialogManager.Config<String> config) {
    
                        }
    
                        @Override
                        void show(DialogManager.Config<String> config) {
                            DialogManager.getInstance().getILog().onPrintLog("DialogManager", "show->" + config.getBaseType().getType());
                            Toast.makeText(context, "String Type show->这是个文字", Toast.LENGTH_SHORT).show();
    
                            new Handler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                  /*需要记住,在合适的地方一定要调用方法config.dispatch()通知DialogManager
                                   *接着展示下个“概念”弹窗
                                   */
                                    config.dispatch();
                                }
                            }, 3000);
                        }
    
                        @Override
                        void dismiss(DialogManager.Config<String> config) {
                            DialogManager.getInstance().getILog().onPrintLog("DialogManager", "dismiss->" + config.getBaseType().getType());
                        }
                    })
                    .priority(2)
                    .onShowCheckListener(new DialogManager.OnShowCheckListener() {
                        @Override
                        public boolean isCanShow() {
                            return true;
                        }
                    })
                    .build();
    

    AlertDialog“概念”弹窗的配置

    AlertDialog alertDialog = new AlertDialog.Builder(context).create();
            alertDialog.setMessage("第三个弹窗");
            alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "我知道了", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    alertDialog.dismiss();
                }
            });
            DialogManager.Config<AlertDialog> config3 = new DialogManager
                    .Config
                    .Builder<AlertDialog>()
                    .as(new DialogManager.BaseType<AlertDialog>(alertDialog) {
                        @Override
                        void init(DialogManager.Config<AlertDialog> config) {
                            config.getBaseType().getType().setOnDismissListener(new DialogInterface.OnDismissListener() {
                                @Override
                                public void onDismiss(DialogInterface dialog) {
                                    config.dispatch();
                                }
                            });
                        }
    
                        @Override
                        void show(DialogManager.Config<AlertDialog> config) {
                            config.getBaseType().getType().show();
                        }
    
                        @Override
                        void dismiss(DialogManager.Config<AlertDialog> config) {
                            config.getBaseType().getType().dismiss();
                        }
                    })
                    .priority(3)
                    .onShowCheckListener(new DialogManager.OnShowCheckListener() {
                        @Override
                        public boolean isCanShow() {
                            return true;
                        }
                    })
                    .build();
    

    将三种“概念”弹窗纳入管理

    DialogManager.getInstance().add(config1);
    DialogManager.getInstance().add(config2);
    DialogManager.getInstance().add(config3);
    

    在需要展示的地方只需要调用

    DialogManager.getInstance().show();
    

    这样我们做到了对“概念”弹窗无代码入侵,待添加的“概念”弹窗对应的Config只需要在合适的地方调用方法config.dispatch()通知DialogManager接着展示下个“概念”弹窗,实现show和dismiss逻辑,实现isCanshow逻辑即可,从代码的角度上来看逻辑更加清晰。

    另外,可调用如下方法设置是否开启调试模式,调试模式带日志

    DialogManager.getInstance().(boolean debug);
    

    可调用如下方法代理调试模式下日志的输出,如

    DialogManager.getInstance().setILog(new DialogManager.ILog() {
                        @Override
                        public void onPrintLog(String TAG, String log) {
                            LogUtil.d(TAG, log);
                        }
                    });
    

    完整的DialogManager代码如下

    import android.util.Log;
    
    import java.util.UUID;
    import java.util.Vector;
    
    /**
     * 作者:lpx on 2021/11/18 17:39
     * Email : 1966353889@qq.com
     * Describe:“概念”弹窗优先级管理(支持设置弹窗优先级)
     * update on 2021/11/20 11:29
     */
    public class DialogManager {
        private final String TAG = "DialogManager";
        /*由于instance = new Singleton(),这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情。
        1.给 instance 分配内存
        2.调用 Singleton 的构造函数来初始化成员变量
        3.将instance对象指向分配的内存空间(执行完这步instance就为非null了)
        但是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。
        我们只需要将 instance 变量声明成 volatile 就可以了。*/
        private static volatile DialogManager mInstance;
        /**
         * 所有已添加的Type集合(线程安全的List,用法和ArrayList类似)
         */
        private Vector<Config> mConfigs = new Vector<>();
        /**
         * 当前正在显示的Type
         */
        private Config mCurrentConfig;
        /**
         * 日志输出类
         */
        private ILog mILog;
        /**
         * 是否调试模式
         */
        private boolean debug = BuildConfig.DEBUG;
    
        private DialogManager() {
            mILog = new ILog() {
                @Override
                public void onPrintLog(String TAG, String log) {
                    Log.d(TAG, log);
                }
            };
        }
    
        /**
         * 打印log(内部调用)
         */
        private void printLog(String log) {
            if (debug && mILog != null) {
                mILog.onPrintLog(TAG, log);
            }
        }
    
    
        /**
         * 尝试移除相同优先级的Config
         */
        private <Type> void tryRemoveType(Config<Type> config) {
            if (mConfigs != null && !mConfigs.isEmpty() && config != null) {
                for (int i = 0, size = mConfigs.size(); i < size; i++) {
                    if (mConfigs.get(i).getPriority() == config.getPriority()) {
                        mConfigs.get(i).dismiss();
                        mConfigs.remove(mConfigs.get(i));
                        break;
                    }
                }
            }
        }
    
        /**
         * 获取已添加的最大优先级的且满足显示条件的Type
         */
        private <Type> Config<Type> getMaxPriorityCanShowType() {
            if (mConfigs != null && !mConfigs.isEmpty()) {
                int size = mConfigs.size();
                int position = size - 1;
                for (int i = size - 1; i >= 0; i--) {
                    if (mConfigs.get(i).isCanShow() && mConfigs.get(i).getPriority() > mConfigs.get(position).getPriority()) {
                        position = i;
                    }
                }
                return mConfigs.get(position).isCanShow() ? mConfigs.get(position) : null;
            }
            return null;
        }
    
        /**
         * 移除对应的Type
         */
        private <Type> void remove(Config<Type> config) {
            if (mConfigs != null && !mConfigs.isEmpty() && config != null) {
                int size = mConfigs.size();
                boolean result = mConfigs.remove(config);
                printLog("remove(object)\nresult:" + result + "\nsize:" + size + "->" + mConfigs.size());
            } else {
                printLog("remove(object)\nresult:does not perform\nsize:" + (mConfigs != null ? mConfigs.size() : "configs is null"));
            }
        }
    
        /**
         * 显示下个Type
         */
        private void showNext() {
            show();
        }
    
        /**
         * 返回当前实例
         */
        public static DialogManager getInstance() {
            if (mInstance == null) {
                synchronized (DialogManager.class) {
                    if (mInstance == null) {
                        mInstance = new DialogManager();
                    }
                }
            }
            return mInstance;
        }
    
        /**
         * 设置对应的log处理类
         */
        public void setILog(ILog log) {
            if (log != null) {
                mILog = log;
            }
        }
    
        public ILog getILog() {
            return mILog;
        }
    
        /**
         * 是否打开调试模式
         */
        public void enableDebug(boolean debug) {
            this.debug = debug;
        }
    
        /**
         * 添加Type(支持添加相同优先级的Type)
         */
        public <Type> void add(Config<Type> config) {
            if (mConfigs != null) {
                mConfigs.add(config);
            }
        }
    
        /**
         * 添加Type(支持添加相同优先级的Type)
         *
         * @param priorityReplace 是否替换存在的相同优先级的Type
         */
        public <Type> void add(Config<Type> config, boolean priorityReplace) {
            if (priorityReplace) {
                tryRemoveType(config);
            }
            if (mConfigs != null) {
                mConfigs.add(config);
            }
        }
    
    
        /**
         * 显示Type
         */
        public <Type> void show() {
            Config<Type> config = getMaxPriorityCanShowType();
            if (config != null) {
                if (mCurrentConfig != null) {
                    if (mCurrentConfig.getUuid().equals(config.getUuid())) {
                        printLog("show()->getMaxPriorityCanShowType()\nresult:success"
                                + "\ntype:" + (config.getBaseType() != null && config.getBaseType().getType() != null ? config.getBaseType().getType().getClass().getSimpleName() : "unknown")
                                + "\npriority:" + config.getPriority()
                                + "\nextra:the same as current type uuid");
                        return;
                    }
                    mCurrentConfig.closeByManager();
                    mCurrentConfig.dismiss();
                }
                printLog("show()->getMaxPriorityCanShowType()\nresult:success"
                        + "\ntype:" + (config.getBaseType() != null && config.getBaseType().getType() != null ? config.getBaseType().getType().getClass().getSimpleName() : "unknown")
                        + "\npriority:" + config.getPriority());
                mCurrentConfig = config;
                config.show();
            } else {
                printLog("show()->getMaxPriorityCanShowType():\nresult:target not found");
            }
        }
    
        /**
         * 日志输出接口
         */
        public interface ILog {
            void onPrintLog(String TAG, String log);
        }
    
        /**
         * Type配置类
         */
        public static class Config<Type> {
            /**
             * 标识码
             */
            private final String uuid;
            /**
             * Type包装类(泛型)
             */
            private BaseType<Type> baseType;
            /**
             * 弹窗优先级(值越大优先级越高)
             */
            private int priority;
            /**
             * 是否通过优先级机制关闭的Type(若为true则可能重新被打开)
             */
            private boolean closeByManager;
            private OnShowCheckListener onShowCheckListener;
            private OnDismissCheckListener onDismissCheckListener;
    
            private Config(Builder<Type> builder) {
                uuid = UUID.randomUUID().toString();
                this.baseType = builder.baseType;
                this.priority = builder.priority;
                this.onShowCheckListener = builder.onShowCheckListener;
                this.onDismissCheckListener = builder.onDismissCheckListener;
                if (this.baseType != null) {
                    this.baseType.init(this);
                }
            }
    
            /**
             * 当前Type是否可以show(不用考虑其它Type的情况)
             */
            private boolean isCanShow() {
                return (getBaseType() != null && getBaseType().getType() != null) && (onShowCheckListener == null || onShowCheckListener.isCanShow());
            }
    
            /**
             * 当前Type是否可以dismiss(不用考虑其它Type的情况)
             */
            private boolean isCanDismiss() {
                return (getBaseType() != null && getBaseType().getType() != null) && (onDismissCheckListener == null || onDismissCheckListener.isCanDismiss());
            }
    
            /**
             * 内部调用
             */
            private void closeByManager() {
                closeByManager = true;
            }
    
            /**
             * 分发事件(Type dismiss后调用)
             */
            protected void dispatch() {
                /*被优先级机制暂时隐藏的弹窗不移除*/
                if (!closeByManager) {
                    DialogManager.getInstance().remove(this);
                }
                DialogManager.getInstance().showNext();
            }
    
            public BaseType<Type> getBaseType() {
                return baseType;
            }
    
            public int getPriority() {
                return priority;
            }
    
            public String getUuid() {
                return uuid;
            }
    
            /**
             * 展示当前Type
             */
            private void show() {
                if (isCanShow()) {
                    /*有些Type是优先级机制暂时关闭的,重新show之后需要重置closeByManager,这样在主动dismiss当前的时候才会remove掉*/
                    closeByManager = false;
                    getBaseType().show(this);
                }
            }
    
            /**
             * 隐藏当前Type
             */
            private void dismiss() {
                if (isCanShow()) {
                    getBaseType().dismiss(this);
                }
            }
    
            public static class Builder<Type> {
                private BaseType<Type> baseType;
                private int priority;
                private OnShowCheckListener onShowCheckListener;
                private OnDismissCheckListener onDismissCheckListener;
    
                public Builder<Type> as(BaseType<Type> baseType) {
                    this.baseType = baseType;
                    return this;
                }
    
                public Builder<Type> priority(int priority) {
                    this.priority = priority;
                    return this;
                }
    
                public Builder<Type> onShowCheckListener(OnShowCheckListener onShowCheckListener) {
                    this.onShowCheckListener = onShowCheckListener;
                    return this;
                }
    
                public Builder<Type> onDismissCheckListener(OnDismissCheckListener onDismissCheckListener) {
                    this.onDismissCheckListener = onDismissCheckListener;
                    return this;
                }
    
                public Config<Type> build() {
                    return new Config<>(this);
                }
    
            }
    
        }
    
        /**
         * Type包装类
         */
        public abstract static class BaseType<Type> {
            private Type type;
    
            public BaseType(Type type) {
                this.type = type;
            }
    
            public Type getType() {
                return type;
            }
    
            abstract void init(Config<Type> config);
    
            abstract void show(Config<Type> config);
    
            abstract void dismiss(Config<Type> config);
        }
    
        /**
         * 当前Type show条件检测(不用考虑其它Type的情况)-默认返回true,可外部实现更改判断条件
         */
        public interface OnShowCheckListener {
            boolean isCanShow();
        }
    
        /**
         * 当前Type dismiss条件检测(不用考虑其它Type的情况)-默认返回true,可外部实现更改判断条件)
         */
        public interface OnDismissCheckListener {
            boolean isCanDismiss();
        }
    }
    

    代码的注释挺详细的,就不做过多说明了,有问题的话可随时联系我或评论区留言。

    在这里插入图片描述

    展开全文
  • PoupoLayer一个通用的Android弹窗管理框架,支持带网络请求的业务流程管理,内部维护弹窗优先级队列 具备弹窗管理扩展功能 整合Dialog,PoupoWindow,悬浮Widget,透明Webview,Toast,SnackBar,无需再为繁琐的业务弹窗...
  • Android弹窗事件

    2020-09-28 15:35:24
    开发工具与关键技术:eclipse、Android 作者:邓婵 撰写时间:2020年 09月28日 首先我们要新建一个适配器,以便于数据在View上显示,下面就是我在适配器中设置点击事件方法以及绑定相关的数据,如图下所示: 接着...
  • Android 全屏弹窗

    千次阅读 2021-12-09 14:46:04
    // 构建Dialog val dialog = Dialog(context) val contentView: View = ...// 获取自定义View里的控件并传值 val tvWishValue: TextView = contentView.findViewById(R.id.tv_wish_value) tvWishValue.tex.
  • implementation 'com.contrarywind:Android-PickerView:4.1.9' public class DialogHelper { public static void showConfirmDialog(Context context, String title, CharSequence content, ...
  • 本文实例为大家分享了Android弹窗控件CustomFiltControl的使用方法,供大家参考,具体内容如下效果:起初踩的坑:刚开始是因为项目中需要用到筛选的功能,以前也遇到过但都是其他同事做的,而我看他们的实现大多都...
  • 前言一直以来 , 作弹窗功能的时候都是使用的Dialog , 布局复杂的弹窗则使用Activity , 把背景设置成透明, 最近了解到一个DialogFragment , 发现使用起来更加方便, 也是谷歌建议的作法.java简介DialogFragment 继承自...
  • Android实现信息弹出框

    2021-05-20 16:03:23
    本文实例为大家分享了Android实现信息弹出框的具体代码,供大家参考,具体内容如下layout下的dialog_common_layout.xmlandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background...
  • 怎么在Android中利用PopupWindow实现一个底部弹窗功能发布时间:2020-12-30 14:02:01来源:亿速云阅读:127作者:Leah这篇文章将为大家详细讲解有关怎么在Android中利用PopupWindow实现一个底部弹窗功能,文章内容...
  • 举个最简单的例子,用iPhone时,QQ或微信有新消息送到时,手机屏幕会自动点亮并弹出提示窗口,用安卓手机时则不同,消息送达就声音响一下,想要查看得进入系统从用手指从屏幕上往下滑动查看消息列表,或者打开相关...
  • Android开发中,时不时的可能要弹出出个窗口,本文为你介绍Android PopupWindow弹窗方面的相关知识,其实Android PopupWindow弹窗,也和AlertDialog对话框类似,本文就先介绍Android PopupWindow弹窗的相关内容,...
  • Android 自定义弹窗框架

    千次阅读 2019-11-22 19:11:36
    Android 自定义弹窗框架前言样式图写一个Base类 BaseDialog建立基本弹窗布局 dialog_def_loading_view.xml写一个按钮样式选择 ButtonStyle写一个按钮点击监听 OnBtnClick自定义弹窗 ButtonDialog使用方法完事 ...
  • 文章目录1. 结果2. 过程2.1. 创建布局文件alert_sign.xml(还拼错了...don't mind)2.2. 使用3....1. 结果 2. 过程 2.1. 创建布局文件alert_sign.xml(还拼错了…don’t mind) ... android:layout_height="match_par
  • Android 自定义弹窗提示 Java文件: private void showSetDeBugDialog() { AlertDialog.Builder setDeBugDialog = new AlertDialog.Builder(this); //获取界面 View dialogView = LayoutInflater.from(this)....
  • 前言在Android圈里关于弹窗的开源框架还是挺多的,但是大多数扩展都是针对于样式,像是一种类型的弹窗开发者传入不同的参数就能在UI效果上显示不同的特效,这样的扩展的确是十分方便但在我们具体工作业务开发中,UI对...
  • 本文实例为大家分享了Android实现弹窗广告的具体代码,供大家参考,具体内容如下内容:弹窗广告特点:根据屏幕尺寸和原图片比例自适应代码如下:package com.example.leixiansheng.addialog;import android....
  • Android下拉选择弹窗

    千次阅读 2021-12-07 09:50:14
    起因呢又是有个需求,也是自己觉得好看,很多app都有下拉选择框,就想着实现下(主要是时间空闲,如果时间少,项目急,就找现成的),先看图片: 直接上代码: xml: <... android:layout_height
  • 一个通用的Android弹窗管理框架,内部维护弹窗优先级队列 具备弹窗管理扩展功能 整合Dialog,PoupoWindow,悬浮Widget,透明Webview,Toast,SnackBar,无需再为繁琐的业务弹窗逻辑所困扰如何添加依赖只需要两行代码轻松...
  • ") .setIcon(android.R.drawable.ic_dialog_info) .setView(inputServer) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which)...
  • Android 弹窗毛玻璃背景实践需求: 点击FloatingActionButton弹出弹层,弹层底部有多个图标可选,每一个图标都是一个功能入口,背景采用毛玻璃模糊效果。记录一下这个需求的思考和实现过程。查找Android原生API做法在...
  • App处理获取权限的弹窗

    千次阅读 2019-08-08 17:44:40
    在做APP自动化的时候经常会遇到启动app后获取一些权限的弹窗了。 方案1:我们在启动先手动打开APP允许获取权限,然后在desired_caps中加上noReset等于True,这样启动APP就不会出现系统自带的权限弹窗了。 desired_caps...
  • // 弹窗获取自定义的布局 dialog.getWindow().setContentView(R.layout.activity_dialog1); //* 这里设置了,就显示这里的文字。把这段代码隐蔽就显示 xml那边的文字 TextView dialogMessage = dialog.findViewById...
  • Android弹窗的简单使用

    2019-09-27 18:23:52
    Android对话框弹窗源自于Dialog类,但是原本的Dialog格式比较单一,相较于现在UI界面的丰富绚丽,显得有些冲突。要想实现个性化的弹窗就需要在原来的Dialog类上做一些拓展。 继承Dialog类: import android....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,734
精华内容 5,493
关键字:

获取安卓弹窗