Android 优雅地管理Dialog弹框

Posted 小混球

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 优雅地管理Dialog弹框相关的知识,希望对你有一定的参考价值。

我们应该都知道任何一个app的UI都会遵循一个统一的样式,比如我们的Dialog、Log、Toast等,统一管理好自己的组件库,对自己或后来人都会有很大地帮助的。

记得自己刚开始接手某个项目时,发现这个项目什么规范都没有,命名啥的也不规范,虽然有一些统一管理的工具类,但是写地真是烂,唉,说多了都是泪。。。。

接下来讲解下小球项目里Dialog,我们项目中Dialog居中显示,属性有标题、内容、按钮(1或2个),如我们的布局文件dialog_common_view.xml
<?xml version="1.0" encoding="utf-8"?>
<com.flyco.roundview.RoundLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:paddingBottom="10dp"
    app:rv_backgroundColor="@color/white"
    app:rv_cornerRadius="6dp">

    <com.flyco.roundview.RoundTextView
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:gravity="center"
        android:id="@+id/tv_dialog_title"
        android:minHeight="50dp"
        android:paddingBottom="4dp"
        android:paddingEnd="15dp"
        android:paddingStart="15dp"
        android:paddingTop="4dp"
        android:text="标题"
        android:textColor="@color/dialog_title_text"
        android:textSize="17sp"
        android:textStyle="bold"
        android:visibility="visible"
        app:rv_backgroundColor="@color/dialog_title_bg"
        app:rv_cornerRadius_TL="6dp"
        app:rv_cornerRadius_TR="6dp" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_marginBottom="25dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginTop="25dp"
        android:layout_width="match_parent"
        android:gravity="center"
        android:id="@+id/tv_dialog_content"
        android:lineSpacingExtra="2dp"
        android:maxHeight="400dp"
        android:scrollbars="vertical"
        android:text="弹框内容"
        android:textColor="@color/dialog_content_text"
        android:textSize="14sp" />


    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_width="match_parent"
        android:id="@+id/ll_bottom_operation"
        android:orientation="horizontal">

        <com.flyco.roundview.RoundTextView
            android:layout_height="40dp"
            android:layout_marginEnd="4dp"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:gravity="center"
            android:id="@+id/rtv_left"
            android:text="@string/dialog_btn_cancel"
            android:textColor="@color/dialog_btn_cancel_text"
            android:textSize="14sp"
            android:visibility="visible"
            app:rv_backgroundColor="@color/dialog_btn_cancel_bg"
            app:rv_backgroundPressColor="@color/dialog_btn_cancel_bg_checked"
            app:rv_cornerRadius="6dp"
            app:rv_strokeColor="@color/dialog_btn_cancel_stroke"
            app:rv_strokePressColor="@color/dialog_btn_cancel_stroke_checked"
            app:rv_strokeWidth="1dp" />

        <com.flyco.roundview.RoundTextView
            android:layout_height="40dp"
            android:layout_marginStart="4dp"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:gravity="center"
            android:id="@+id/rtv_right"
            android:text="@string/dialog_btn_confirm"
            android:textColor="@color/dialog_btn_confirm_text"
            android:textSize="14sp"
            android:visibility="visible"
            app:rv_backgroundColor="@color/dialog_btn_confirm_bg"
            app:rv_backgroundPressColor="@color/dialog_btn_confirm_bg_checked"
            app:rv_cornerRadius="6dp" />

    </LinearLayout>
</com.flyco.roundview.RoundLinearLayout>

用到的依赖
    implementation 'com.blankj:utilcodex:1.30.6'
    implementation 'com.flyco.roundview:FlycoRoundView_Lib:1.1.4@aar'
颜色值
    <!--弹框相关颜色-->
    <color name="dialog_title_text">#101a3e</color>
    <color name="dialog_title_bg">#F9FAFB</color>
    <color name="dialog_content_text">#221715</color>

    <color name="dialog_btn_cancel_text">#221715</color>
    <color name="dialog_btn_cancel_stroke">#221715</color>
    <color name="dialog_btn_cancel_stroke_checked">#221715</color>
    <color name="dialog_btn_cancel_bg">#FFFFFF</color>
    <color name="dialog_btn_cancel_bg_checked">#F0F0F0</color>

    <color name="dialog_btn_confirm_text">#221715</color>
    <color name="dialog_btn_confirm_stroke">#221715</color>
    <color name="dialog_btn_confirm_stroke_checked">#221715</color>
    <color name="dialog_btn_confirm_bg">#4996F3</color>
    <color name="dialog_btn_confirm_bg_checked">#4996F3</color>

    <color name="dialog_btn_confirm_text_enable">#80221715</color>
    <color name="dialog_btn_confirm_bg_enable">#384996F3</color>
字符值
    <string name="dialog_title">温馨提示</string>
    <string name="dialog_permission_allow">允许</string>
    <string name="dialog_permission_refuse">拒绝</string>
    <string name="dialog_permission_title">申请权限</string>
    <string name="dialog_btn_cancel">取消</string>
    <string name="dialog_btn_confirm">确认</string>
    <string name="dialog_btn_setting">设置</string>
以前项目中Dialog这里写一个,那边又写一个,所以自己就重构了整个项目的Dialog,先是定义了个简单基类BaseDialog
package com.littlejerk.permissiondemo;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;

import com.blankj.utilcode.util.ActivityUtils;

import androidx.annotation.NonNull;

/**
 * @author : HHotHeart
 * @date : 2021/9/17 12:46
 * @desc : 描述
 */
public class BaseDialog extends Dialog {
    private Context context;


    public BaseDialog(@NonNull Context context) {
        super(context, R.style.DialogTheme);
        this.context = context;
    }


    /**
     * Dialog显示前处理逻辑
     *
     * @param view Dialog内容布局
     */
    public void show(View view) {
        Window window = getWindow();
        if (window == null) return;
        window.setContentView(view);
        WindowManager.LayoutParams pl = window.getAttributes();
        pl.gravity = Gravity.CENTER; //位置
        pl.height = WindowManager.LayoutParams.WRAP_CONTENT;
        int width = window.getDecorView().getResources().getDisplayMetrics().widthPixels;
        pl.width = (int) (width * 0.9);
        window.setAttributes(pl);
        show();
    }

    @Override
    public void show() {
        Activity activity = ActivityUtils.getActivityByContext(context);
        if (activity != null && !activity.isFinishing()) {
            super.show();
        }
    }

    @Override
    public void dismiss() {
        Activity activity = ActivityUtils.getActivityByContext(context);
        if (activity != null && !activity.isFinishing()) {
            super.dismiss();
        }
    }

    /**
     * 是否是外部区域
     *
     * @param context
     * @param event
     * @return
     */
    public boolean isOutOfBounds(Context context, MotionEvent event) {

        final int x = (int) event.getX();
        final int y = (int) event.getY();

        final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
        final Window window = getWindow();
        if (window == null) return false;
        final View decorView = getWindow().getDecorView();
        return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > (decorView.getHeight() + slop));
    }
}
然后使用单例模式AppDialogManager来管理Dialog,如下是完整的代码
package com.littlejerk.permissiondemo;


import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.StringUtils;
import com.flyco.roundview.RoundTextView;

/**
 * @author : HHotHeart
 * @date : 2021/8/21 01:03
 * @desc : Dialog公共管理类
 */
public class AppDialogManager {

    private AppDialogManager() {
    }

    public static AppDialogManager getInstance() {
        return Holder.instance;
    }

    private static class Holder {
        private static AppDialogManager instance = new AppDialogManager();
    }

    /**
     * 普通弹框-只有一个实例的弹框
     */
    private BaseDialog mDialog = null;

    /**
     * 扩展的Dialog回调
     */
    public interface DialogClickCallback {
        void onClick(int index);
    }

    /**
     * 权限申请弹框
     *
     * @param activity
     * @param content
     * @param positiveLister
     */
    public void showPermissionRemindDialog(Activity activity, String content,
                                           DialogInterface.OnClickListener negativeLister, DialogInterface.OnClickListener positiveLister) {
        showCommonDialog(activity,
                activity.getString(R.string.dialog_permission_title), content,
                activity.getString(R.string.dialog_permission_refuse), negativeLister,
                activity.getString(R.string.dialog_permission_allow), positiveLister);
    }

    /**
     * 权限设置弹框提示
     *
     * @param activity
     * @param content
     * @param positiveLister
     */
    public void showPermissionSettingRemind(Activity activity, String content,
                                            DialogInterface.OnClickListener negativeLister, DialogInterface.OnClickListener positiveLister) {
        showCommonDialog(activity,
                activity.getString(R.string.dialog_permission_title), content,
                activity.getString(R.string.dialog_btn_cancel), negativeLister,
                activity.getString(R.string.dialog_btn_setting), positiveLister);
    }

    /**
     * 有Positive按钮的Dialog
     *
     * @param activity
     * @param title
     * @param content
     * @param positive
     * @param positiveLister
     */
    public void showPositiveDialog(Activity activity, String title, String content,
                                   String positive, DialogInterface.OnClickListener positiveLister) {
        showCommonDialog(activity, title, content, null, null, positive, positiveLister);
    }

    /**
     * 有确认和取消按钮(没有title)
     *
     * @param activity
     * @param content
     * @param positiveLister
     */
    public void showCommonDialog(Activity activity, String content, DialogInterface.OnClickListener positiveLister) {
        showCommonDialog(activity, null, content,
                activity.getString(R.string.dialog_btn_cancel), null,
                activity.getString(R.string.dialog_btn_confirm), positiveLister);
    }

    /**
     * 公共方法
     *
     * @param activity
     * @param title
     * @param content
     * @param negative
     * @param negativeLister
     * @param positive
     * @param positiveLister
     */
    public void showCommonDialog(Activity activity, String title, String content,
                                 String negative, DialogInterface.OnClickListener negativeLister,
                                 String positive, DialogInterface.OnClickListener positiveLister) {
        showCommonDialog(activity, title, content, negative, negativeLister, positive, positiveLister, true);
    }

    /**
     * 公共方法
     *
     * @param activity
     * @param title
     * @param content
     * @param negative
     * @param negativeLister
     * @param positive
     * @param positiveLister
     * @param isClickDismiss
     */
    public void showCommonDialog(Activity activity, String title, String content,
                                 String negative, DialogInterface.OnClickListener negativeLister,
                                 String positive, DialogInterface.OnClickListener positiveLister, boolean isClickDismiss) {
        showDialog(activity, title, content, negative, negativeLister, positive, positiveLister,
                false, false, null,
                true, isClickDismiss);
    }


    /**
     * Dialog基本方法
     *
     * @param activity                 显示Dialog的Activity
     * @param title                    Dialog 标题
     * @param content                  Dialog 内容
     * @param negative                 左边按钮
     * @param negativeLister           左边按钮的点击事件
     * @param positive                 右边按钮
     * @param positiveLister           右边按钮的点击事件
     * @param isCanceledOnTouchOutside 点击非Dialog内容部分是否允许Dismiss
     * @param isCancelable             点击后退键是否允许Dismiss
     * @param dismissListener          Dialog消失的监听事件
     * @param isMultiDialog            是否允许多个Dialog同时存在
     * @param isClickDismiss           点击按钮是否允许dismiss Dialog
     */
    private void showDialog(Activity activity,
                            String title,
                            String content,
                            String negative, final DialogInterface.OnClickListener negativeLister,
                            String positive, final DialogInterface.OnClickListener positiveLister,
                            boolean isCanceledOnTouchOutside,
                            boolean isCancelable,
                            final DialogInterface.OnDismissListener dismissListener,
                            boolean isMultiDialog,
                            final boolean isClickDismiss) {

        View view = LayoutInflater.from(activity).inflate(R.layout.dialog_common_view, null);
        TextView tvTitle = view.findViewById(R.id.tv_dialog_title);
        TextView tvContent = view.findViewById(R.id.tv_dialog_content);
        tvContent.setMovementMethod(ScrollingMovementMethod.getInstance());
        RoundTextView rtvLeft = view.findViewById(R.id.rtv_left);
        以上是关于Android 优雅地管理Dialog弹框的主要内容,如果未能解决你的问题,请参考以下文章

Android开源库-BottomDialog两种样式弹框

Android开源库-BottomDialog两种样式弹框

Android开源库-BottomDialog两种样式弹框

Vue+ElementUI中 el-dialog弹框蒙层问题

Vue+ElementUI中 el-dialog弹框蒙层问题

Android应用中如何自定义弹框?