1. 概述

  • github 地址 : https://github.com/luoshenzhi/UniversalDialog.git

1.1 特点说明

  1. 代码简洁, 不需要其他资源文件, 使用方便, 可定制性高
  2. 基于 DialogFragment 实现, 避免 Activity 销毁了对话框还存在
  3. 基于 AppCompatDialogFragment 实现, 确保 Android 各版本样式兼容
  4. 支持设置圆角、横坚屏切换、显示动画、位置、大小等
  5. 支持横坚屏切换保存控件状态, 如 EditText 数据

1.2 注意事项

  • 默认使用 AppCompatDialogFragment, 必须添加 AppCompat 依赖并设置主题, 如果不想使用, 让 UniversalDialog 继承 DialogFragment 即可
// 1. 添加依赖 appcompatdependencies {    implementation 'com.android.support:appcompat-v7:28.0.0'}// 2. 使用 AppCompat 的主题<resources>    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">       ..........    style>resources>

2. 使用方式

2.1 MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Button button = new Button(this);        button.setOnClickListener(this);        button.setText("Hello");        button.setLayoutParams(new ViewGroup.LayoutParams(200, 100));        setContentView(button);    }    @Override    public void onClick(View v) {        UniversalDialog.Builder                .setView(R.layout.dialog_layout)                        // 设置布局文件                .setWidth(800)                                          // 设置宽                .setHeight(500)                                         // 设置高                .setGravity(Gravity.CENTER)                             // 设置位置                .setRoundRadius(15)                                     // 设置圆角                .setAnimation(android.R.style.Animation_Translucent)    // 设置动画                .setDimAmount(0.5f)                                     // 设置背景透明度                .setCancelable(false)                                   // 设置为强制对话框                .setOnBindViewListener((dialog, holder) -> {            // 设置布局                    holder.setOnClickListener(R.id.no_tv, (view) -> dialog.dismiss());                    holder.setOnClickListener(R.id.yes_tv, (view) -> dialog.dismiss());                })                .setOnSaveStateListener((outState, holder, resume) -> { // 保存 View 状态                    // 恢复数据                    final String key = "password_et";                    if (resume) {                        String password = outState.getString(key);                        holder.setText(R.id.password_et, password);                        return;                    }                    // 保存数据                    String password = holder.getView(R.id.password_et).toString().trim();                    if (!TextUtils.isEmpty(password)) {                        outState.putString(key, password);                    }                })                .create()                                                // 创建对话框                .show(getSupportFragmentManager(), "TAG");    }}

2.2 dialog_layout.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="match_parent"    android:background="@android:color/holo_blue_dark"    android:orientation="vertical"    android:padding="15dp">    <TextView        android:id="@+id/title_tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="提示" />    <TextView        android:id="@+id/message_tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="请输入您的密码" />    <EditText        android:id="@+id/password_et"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="15dp"        android:gravity="right|end"        android:orientation="horizontal">        <TextView            android:id="@+id/no_tv"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="No" />        <TextView            android:id="@+id/yes_tv"            android:layout_width="wrap_content"            android:layout_marginLeft="20dp"            android:layout_height="wrap_content"            android:text="Yes" />    LinearLayout>LinearLayout>

2.3 UniversalDialog.java

package com.ken.dialog;import android.content.Context;import android.graphics.Color;import android.graphics.drawable.GradientDrawable;import android.os.Bundle;import android.os.Parcel;import android.os.Parcelable;import android.support.annotation.LayoutRes;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.annotation.StyleRes;import android.support.v4.app.DialogFragment;import android.support.v7.app.AppCompatDialogFragment;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.view.WindowManager;/** * 通用对话框 * @author Ken Luo * @version 1.0 */public class UniversalDialog extends AppCompatDialogFragment {    private DialogParams params;    private ViewHolder viewHolder;    private static final String SAVE_STATE_KEY = "params";    @Nullable    @Override    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        return setView(inflater, container, savedInstanceState);    }    @Override    public void onStart() {        super.onStart();        setDialog();    }    @Override    public void onSaveInstanceState(@NonNull Bundle outState) {        super.onSaveInstanceState(outState);        outState.putParcelable(SAVE_STATE_KEY, params);                     // 横坚屏切换时保存数据        if (params.saveStateListener != null) {            params.saveStateListener.onSaveInstanceState(outState, viewHolder, false);        }    }    private void setParams(DialogParams params) {        this.params = params;    }    private View setView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        // 恢复横坚屏切换时保存的对话框数据        if (params == null && savedInstanceState != null) {            params = savedInstanceState.getParcelable(SAVE_STATE_KEY);        }        if (params == null || params.layoutResId <= 0)            return null;        View view = inflater.inflate(params.layoutResId, container, false);        viewHolder = new ViewHolder(getContext(), view);        // 设置布局        if (params.bindViewListener != null) {            params.bindViewListener.onBindView(this, viewHolder);        }        // 恢复 View 状态, 如 EditText 的数据        if (params.saveStateListener != null && savedInstanceState != null) {            params.saveStateListener.onSaveInstanceState(savedInstanceState, viewHolder, true);        }        return view;    }    private void setDialog() {        if (params == null || getContext() == null || getDialog() == null || getDialog().getWindow() == null)            return;        // 圆角背景        Window window = getDialog().getWindow();        GradientDrawable drawable = new GradientDrawable();        drawable.setColor(Color.TRANSPARENT);        drawable.setCornerRadius(params.roundRadius > 0 ? params.roundRadius : dp2px(getContext(), 5));        drawable.setStroke(0, Color.TRANSPARENT);        window.setBackgroundDrawable(drawable);        // 背景变暗        window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);        window.setDimAmount(params.dimAmount);        // 设置宽高和位置        window.setLayout(params.width > 0 ? params.width : getScreenWidth(getContext()) / 4 * 3,                         params.height > 0 ? params.height : WindowManager.LayoutParams.WRAP_CONTENT);        window.setGravity(params.gravity);        // 设置显示和退出动画        if (params.animation > 0)            window.setWindowAnimations(params.animation);        // 是否为强制对话框        this.setCancelable(params.cancelable);    }    private static int getScreenWidth(Context context) {        return context.getResources().getDisplayMetrics().widthPixels;    }    private static int dp2px(Context context, int dps) {        return Math.round(context.getResources().getDisplayMetrics().density * dps);    }    /**     * 通用对话框构建器     */    public static class Builder {        private final DialogParams P;        private Builder(@LayoutRes  int layoutResId) {            P = new DialogParams();            P.layoutResId = layoutResId;        }        /**         * 设置对话框布局         * @param layoutResId : 布局文件         * @return 对话框构建器         */        public static Builder setView(@LayoutRes  int layoutResId) {            return new Builder(layoutResId);        }        /**         * 设置对话框构宽度         * @param width : 对话框宽度, 默认为屏幕宽度的 3/4         * @return 对话框构建器         */        public Builder setWidth(int width) {            P.width = width;            return this;        }        /**         * 设置对话框构高度         * @param height 高度, 默认 WRAP_CONTENT         * @return 对话框构建器         */        public Builder setHeight(int height) {            P.height = height;            return this;        }        /**         * 设置对话框显示位置         * @param gravity 显示位置, 默认 Gravity.CENTER         * @return 对话框构建器         */        public Builder setGravity(int gravity) {            P.gravity = gravity;            return this;        }        /**         * 设置对话框构圆角大小         * @param roundRadius 圆角大小, 默认 5dip         * @return 对话框构建器         */        public Builder setRoundRadius(int roundRadius) {            P.roundRadius = roundRadius;            return this;        }        /**         * 设置显示和退出动画         * @param resId 资源文件         * @return 对话框构建器         *         * 
         *              *         *               *               *                   *                   *               *         *               *               *                   *                   *               *         * 
*/
public Builder setAnimation(@StyleRes int resId) { P.animation = resId; return this; } /** * 设置窗口透明度 * @param dimAmount 范围 0~1.0, 0-完全透明, 1-全黑; 默认 0.5f * @return 对话框构建器 */ public Builder setDimAmount(float dimAmount) { P.dimAmount = dimAmount; return this; } /** * 设置是否为强制对话框 * @param cancelable true 非强制, false 强制; 默认为非强制 * @return 对话框构建器 */ public Builder setCancelable(boolean cancelable) { P.cancelable = cancelable; return this; } /** * 设置布局监听器 * @param listener 对话框布局设置监听器 * @return 对话框构建器 */ public Builder setOnBindViewListener(OnBindViewListener listener) { P.bindViewListener = listener; return this; } public Builder setOnSaveStateListener(OnSaveStateListener listener) { P.saveStateListener = listener; return this; } /** * 创建对话框 * @return 创建好的对话框 * @exception NullPointerException 如果布局文件 ID 小于等于 0 */ public DialogFragment create() { if (P.layoutResId <= 0) throw new NullPointerException("The dialog without layout!"); final UniversalDialog dialog = new UniversalDialog(); dialog.setParams(P); return dialog; } } private static class DialogParams implements Parcelable { private int layoutResId = 0; private int width = 0; private int height = 0; private int gravity = Gravity.CENTER; private int roundRadius = 0; private int animation = 0; private float dimAmount = 0.5f; private boolean cancelable = true; private OnBindViewListener bindViewListener; private OnSaveStateListener saveStateListener; private DialogParams() { } DialogParams(Parcel in) { layoutResId = in.readInt(); width = in.readInt(); height = in.readInt(); gravity = in.readInt(); roundRadius = in.readInt(); animation = in.readInt(); dimAmount = in.readFloat(); cancelable = in.readByte() != 0; } public static final Creator<DialogParams> CREATOR = new Creator<DialogParams>() { @Override public DialogParams createFromParcel(Parcel in) { return new DialogParams(in); } @Override public DialogParams[] newArray(int size) { return new DialogParams[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(layoutResId); dest.writeInt(width); dest.writeInt(height); dest.writeInt(gravity); dest.writeInt(roundRadius); dest.writeInt(animation); dest.writeFloat(dimAmount); dest.writeByte((byte) (cancelable ? 1 : 0)); } } public interface OnBindViewListener { void onBindView(DialogFragment dialog, ViewHolder holder); } public interface OnSaveStateListener { /** * 控件状态保存回调函数 * @param bundle 保存或恢复数据 * @param holder ViewHolder * @param resume true 表示恢复数据, false 表示保存数据 */ void onSaveInstanceState(@NonNull Bundle bundle, ViewHolder holder, boolean resume); }}

更多相关文章

  1. 开源项目之Android DataFramework(数据库框架)
  2. Android studio查看SQLIte数据库文件
  3. Android 数据库事务的个人理解
  4. Android 软键盘将指定的布局顶上去
  5. [图文]为移植到Android平台上的Cocos2d-x项目添加xml布局文件
  6. 使用openFileInput和openFileOutput实现Android平台的数据存储
  7. 定制Android设备的关机对话框
  8. [转]SimpleCursorAdapter类与数据绑定

随机推荐

  1. 解决 Android(安卓)N 上报错:android.os.F
  2. 7-framework--详解 8 Android平台开发-WI
  3. android中常常会遇到与context和getAppli
  4. Android(安卓)ActivityThread(主线程或UI
  5. Android实战简易教程-第二十七枪(Android
  6. Android(安卓)VOIP拨打电话机制分析
  7. 用sdk的tools来打包apk
  8. android Activity 之 startActivityForRe
  9. [android] 从 SDcard 中进行文件的读取操
  10. Android(安卓)背景颜色处理[使用 Drawabl