Android 几个简单的自定义对话框介绍

46 篇文章 0 订阅

Android 几个简单的自定义对话框介绍

一、前言

Android 对话框直接使用肯定是不好看的,如果需要添加取消和确定按钮,肯定是需要进行自定义修改的。

本文简单介绍一个简单的可扩展的对话框,并且支持不同类型样式,加了点小动画。

有需要的可以看看。

二、对话框相关内容

1、效果

在这里插入图片描述

七个demo对话框显示,项目中可以根据实际情况进行使用。

原生对话框标题和内容是靠左的,如果显示默认的按钮是靠右下角的。

自定义的对话框则可以自己决定居中还是靠左和显示自己需要的图片。

2、对话框显示的调用代码

(1)原生对话框代码:
Dialog alertDialog = new AlertDialog.Builder(this).
    setTitle("对话框的标题").
    setMessage("对话框的内容").
    setIcon(R.drawable.ic_launcher).
    create();
alertDialog.show();

虽然 原生的AlertDialog 调用不复杂,但是显示有点丑,并且大小在不同设备上显示大小是不一样的。

AlertDialog 也是可以行决定是否显示确定和取消按钮的,监听setPositiveButton和setNegativeButton方法即可。

(2)自定义对话框代码:
 //(1)默认字符串显示,显示一个确认按钮,只是用来测试
 new SweetAlertDialog(this).show();
 
  //(2)修改标题和文本内容,显示一个确认按钮
 new SweetAlertDialog(this)
 .setTitleText("Title!")
 .setContentText("It's pretty, isn't it?")
 .show();
 
   //(3)修改标题和文本内容和类型图标,显示一个确认按钮
 new SweetAlertDialog(this, SweetAlertDialog.CUSTOM_IMAGE_TYPE)
 .setTitleText("Sweet!")
 .setContentText("Here's a custom image.")
 .setCustomImage(R.drawable.custom_img)
 .show();
 
 大部分场景上面三个代码比较常用。
 
 SweetAlertDialog 的类别,一种有五种,每种类别会选择不同的图标显示。
    public static final int NORMAL_TYPE = 0;
    public static final int ERROR_TYPE = 1;
    public static final int SUCCESS_TYPE = 2;
    public static final int WARNING_TYPE = 3;
    public static final int CUSTOM_IMAGE_TYPE = 4;
 
    //(4)修改标题和文本内容和类型图标,显示一个确认按钮,确定后执行相应的动作
 new SweetAlertDialog(this, SweetAlertDialog.SUCCESS_TYPE)
 .setTitleText("Good job!")
 .setContentText("You clicked the button!")
 .setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
         @Override
         public void onClick(SweetAlertDialog sDialog) {
         // reuse previous dialog instance
         Toast.makeText(SampleActivity.this, "confirm" ,Toast.LENGTH_SHORT).show();
         sDialog.dismiss();
        }
	})
.show();
 
    //(5)修改标题和文本内容和类型图标,点击第一次确定后,还要点一次确定
 new SweetAlertDialog(this, SweetAlertDialog.WARNING_TYPE)
 .setTitleText("Are you sure?")
 .setContentText("Won't be able to recover this file!")
 .setCancelText("No,cancel plx!")
 .setConfirmText("Yes,delete it!")
 .showCancelButton(true)
 .setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() {
     @Override
     public void onClick(SweetAlertDialog sDialog) {
         // reuse previous dialog instance
         sDialog.setTitleText("Cancelled!")
         .setContentText("Your imaginary file is safe :)")
         .setConfirmText("OK")
         .showCancelButton(false)
         .setCancelClickListener(null)
         .setConfirmClickListener(null)
         .changeAlertType(SweetAlertDialog.ERROR_TYPE);
         
        // or you can new a SweetAlertDialog to show

    }
})
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
    @Override
    public void onClick(SweetAlertDialog sDialog) {
        sDialog.setTitleText("Deleted!")
        .setContentText("Your imaginary file has been deleted!")
        .setConfirmText("OK")
        .showCancelButton(false)
        .setCancelClickListener(null)
        .setConfirmClickListener(null)
        .changeAlertType(SweetAlertDialog.SUCCESS_TYPE);
    }
})
.show();

项目中可以根据实际情况进行适配修改,显示一个按钮还是两个按钮都是可以选择的。

3、对话框SweetAlertDialog 主要实现代码:

package com.my.beautifuldialog;


import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Transformation;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class SweetAlertDialog extends Dialog implements View.OnClickListener {
    private View mDialogView;
    private AnimationSet mModalInAnim;
    private AnimationSet mModalOutAnim;
    private Animation mOverlayOutAnim;
    private Animation mErrorInAnim;
    private AnimationSet mErrorXInAnim;
    private AnimationSet mSuccessLayoutAnimSet;
    private Animation mSuccessBowAnim;
    private TextView mTitleTextView;
    private TextView mContentTextView;
    private String mTitleText;
    private String mContentText;
    private boolean mShowCancel;
    private String mCancelText;
    private String mConfirmText;
    private int mAlertType;
    private FrameLayout mErrorFrame;
    private FrameLayout mSuccessFrame;
    private SuccessTickView mSuccessTick;
    private ImageView mErrorX;
    private View mSuccessLeftMask;
    private View mSuccessRightMask;
    private Drawable mCustomImgDrawable;
    private ImageView mCustomImage;
    private Button mConfirmButton;
    private Button mCancelButton;
    private FrameLayout mWarningFrame;
    private OnSweetClickListener mCancelClickListener;
    private OnSweetClickListener mConfirmClickListener;
    private boolean mCanceledOnTouchOutside = false;

    public static final int NORMAL_TYPE = 0;
    public static final int ERROR_TYPE = 1;
    public static final int SUCCESS_TYPE = 2;
    public static final int WARNING_TYPE = 3;
    public static final int CUSTOM_IMAGE_TYPE = 4;

    public static interface OnSweetClickListener {
        public void onClick(SweetAlertDialog sweetAlertDialog);
    }

    public SweetAlertDialog(Context context) {
        this(context, NORMAL_TYPE);
    }

    public SweetAlertDialog(Context context, int alertType) {
        super(context, R.style.alert_dialog);
        setCancelable(true);
        setCanceledOnTouchOutside(false);
        mAlertType = alertType;
        mErrorInAnim = OptAnimationLoader.loadAnimation(getContext(), R.anim.error_frame_in);
        mErrorXInAnim = (AnimationSet)OptAnimationLoader.loadAnimation(getContext(), R.anim.error_x_in);
        // 2.3.x system don't support alpha-animation on layer-list drawable
        // remove it from animation set
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { //Android3 一下,其实没啥必要判断了
            List<Animation> childAnims = mErrorXInAnim.getAnimations();
            int idx = 0;
            for (;idx < childAnims.size();idx++) {
                if (childAnims.get(idx) instanceof AlphaAnimation) {
                    break;
                }
            }
            if (idx < childAnims.size()) {
                childAnims.remove(idx);
            }
        }
        mSuccessBowAnim = OptAnimationLoader.loadAnimation(getContext(), R.anim.success_bow_roate);
        mSuccessLayoutAnimSet = (AnimationSet)OptAnimationLoader.loadAnimation(getContext(), R.anim.success_mask_layout);
        mModalInAnim = (AnimationSet) OptAnimationLoader.loadAnimation(getContext(), R.anim.modal_in);
        mModalOutAnim = (AnimationSet) OptAnimationLoader.loadAnimation(getContext(), R.anim.modal_out);
        mModalOutAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mDialogView.setVisibility(View.GONE);
                mDialogView.post(new Runnable() {
                    @Override
                    public void run() {
                        SweetAlertDialog.super.dismiss();
                    }
                });
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        // dialog overlay fade out
        mOverlayOutAnim = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                WindowManager.LayoutParams wlp = getWindow().getAttributes();
                wlp.alpha = 1 - interpolatedTime;
                getWindow().setAttributes(wlp);
            }
        };
        mOverlayOutAnim.setDuration(120);
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.alert_dialog);
        mDialogView = getWindow().getDecorView().findViewById(android.R.id.content);
        mTitleTextView = (TextView)findViewById(R.id.title_text);
        mContentTextView = (TextView)findViewById(R.id.content_text);
        mErrorFrame = (FrameLayout)findViewById(R.id.error_frame);
        mErrorX = (ImageView)mErrorFrame.findViewById(R.id.error_x);
        mSuccessFrame = (FrameLayout)findViewById(R.id.success_frame);
        mSuccessTick = (SuccessTickView)mSuccessFrame.findViewById(R.id.success_tick);
        mSuccessLeftMask = mSuccessFrame.findViewById(R.id.mask_left);
        mSuccessRightMask = mSuccessFrame.findViewById(R.id.mask_right);
        mCustomImage = (ImageView)findViewById(R.id.custom_image);
        mWarningFrame = (FrameLayout)findViewById(R.id.warning_frame);
        mConfirmButton = (Button)findViewById(R.id.confirm_button);
        mCancelButton = (Button)findViewById(R.id.cancel_button);

        mConfirmButton.setOnClickListener(this);
        mCancelButton.setOnClickListener(this);

        setTitleText(mTitleText);
        setContentText(mContentText);
        showCancelButton(mShowCancel);
        setCancelText(mCancelText);
        setConfirmText(mConfirmText);
        changeAlertType(mAlertType, true);
//        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
    }

    private void restore () {
        mCustomImage.setVisibility(View.GONE);
        mErrorFrame.setVisibility(View.GONE);
        mSuccessFrame.setVisibility(View.GONE);
        mWarningFrame.setVisibility(View.GONE);

        mConfirmButton.setBackgroundResource(R.drawable.blue_button_background);
        mErrorFrame.clearAnimation();
        mErrorX.clearAnimation();
        mSuccessTick.clearAnimation();
        mSuccessLeftMask.clearAnimation();
        mSuccessRightMask.clearAnimation();
    }

    private void playAnimation () {
        if (mAlertType == ERROR_TYPE) {
            mErrorFrame.startAnimation(mErrorInAnim);
            mErrorX.startAnimation(mErrorXInAnim);
        } else if (mAlertType == SUCCESS_TYPE) {
            mSuccessTick.startTickAnim();
            mSuccessRightMask.startAnimation(mSuccessBowAnim);
        }
    }

    private void changeAlertType(int alertType, boolean fromCreate) {
        mAlertType = alertType;
        // call after created views
        if (mDialogView != null) {
            if (!fromCreate) {
                // restore all of views state before switching alert type
                restore();
            }
            switch (mAlertType) {
                case ERROR_TYPE:
                    mErrorFrame.setVisibility(View.VISIBLE);
                    break;
                case SUCCESS_TYPE:
                    mSuccessFrame.setVisibility(View.VISIBLE);
                    // initial rotate layout of success mask
                    mSuccessLeftMask.startAnimation(mSuccessLayoutAnimSet.getAnimations().get(0));
                    mSuccessRightMask.startAnimation(mSuccessLayoutAnimSet.getAnimations().get(1));
                    break;
                case WARNING_TYPE:
                    mConfirmButton.setBackgroundResource(R.drawable.red_button_background);
                    mWarningFrame.setVisibility(View.VISIBLE);
                    break;
                case CUSTOM_IMAGE_TYPE:
                    setCustomImage(mCustomImgDrawable);
                    break;
            }
            if (!fromCreate) {
                playAnimation();
            }
        }
    }

    public int getAlerType () {
        return mAlertType;
    }

    public void changeAlertType(int alertType) {
        changeAlertType(alertType, false);
    }


    public String getTitleText () {
        return mTitleText;
    }

    //解决dialog.setCanceledOnTouchOutside(true) 不生效问题
    public void setDialogTouchOutsideCloseable(Dialog dialog, int gravity) {
        Window window = dialog.getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.width = ViewGroup.LayoutParams.MATCH_PARENT;
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        window.setAttributes(params);
        window.setGravity(gravity);

    }

    //设置点击外部消失
    public SweetAlertDialog setCanceledOutside(boolean cancel) {
        setCanceledOnTouchOutside(cancel);
        return this;
    }

    //设置标题
    public SweetAlertDialog setTitleText (String text) {
        mTitleText = text;
        if (mTitleTextView != null && mTitleText != null) {
            mTitleTextView.setText(mTitleText);
        }
        return this;
    }

    //设置标题上方图标,Drawable 对象
    public SweetAlertDialog setCustomImage (Drawable drawable) {
        mCustomImgDrawable = drawable;
        if (mCustomImage != null && mCustomImgDrawable != null) {
            mCustomImage.setVisibility(View.VISIBLE);
            mCustomImage.setImageDrawable(mCustomImgDrawable);
        }
        return this;
    }

    //设置标题上方图标,Drawable int值
    public SweetAlertDialog setCustomImage (int resourceId) {
        return setCustomImage(getContext().getResources().getDrawable(resourceId));
    }

    public String getContentText () {
        return mContentText;
    }

    //设置显示内容
    public SweetAlertDialog setContentText (String text) {
        mContentText = text;
        if (mContentTextView != null && mContentText != null) {
            mContentTextView.setVisibility(View.VISIBLE);
            mContentTextView.setText(mContentText);
        }
        return this;
    }

    public boolean isShowCancelButton () {
        return mShowCancel;
    }

    //显示取消按钮
    public SweetAlertDialog showCancelButton (boolean isShow) {
        mShowCancel = isShow;
        if (mCancelButton != null) {
            mCancelButton.setVisibility(mShowCancel ? View.VISIBLE : View.GONE);
        }
        return this;
    }

    public String getCancelText () {
        return mCancelText;
    }

    //设置取消按钮的文字
    public SweetAlertDialog setCancelText (String text) {
        mCancelText = text;
        if (mCancelButton != null && mCancelText != null) {
            mCancelButton.setText(mCancelText);
        }
        return this;
    }

    public String getConfirmText () {
        return mConfirmText;
    }

    //设置确认按钮的文字
    public SweetAlertDialog setConfirmText (String text) {
        mConfirmText = text;
        if (mConfirmButton != null && mConfirmText != null) {
            mConfirmButton.setText(mConfirmText);
        }
        return this;
    }

    public SweetAlertDialog setCancelClickListener (OnSweetClickListener listener) {
        mCancelClickListener = listener;
        return this;
    }

    public SweetAlertDialog setConfirmClickListener (OnSweetClickListener listener) {
        mConfirmClickListener = listener;
        return this;
    }

    protected void onStart() {
        mDialogView.startAnimation(mModalInAnim);
        playAnimation();
    }

    public void dismiss() {
        mConfirmButton.startAnimation(mOverlayOutAnim);
        mDialogView.startAnimation(mModalOutAnim);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.cancel_button) {
            if (mCancelClickListener != null) {
                mCancelClickListener.onClick(SweetAlertDialog.this);
            } else {
                dismiss();
            }
        } else if (v.getId() == R.id.confirm_button) {
            if (mConfirmClickListener != null) {
                mConfirmClickListener.onClick(SweetAlertDialog.this);
            } else {
                dismiss();
            }
        }
    }
}

4、优点和缺点

(1)优点
显示方便UI好看
调用api简单方便
确定和取消按钮可以选择显示一个或者两个
添加了不同类别图标,并且图标会显示动画效果
扩展了点击一次确定后,还可以进行多次弹框的情况

(2)缺点
对话框显示的大小基本固定,适合简单信息的显示
对话框无法设置点击周边就消失,因为已经全局显示了
(3)其他扩展

可以用来做自定义Toast。

具体实现思路是:自定义几秒后,执行dismiss关闭对话框。

三、其他

1、小结

网上有千千万万中自定义对话框,各种花里胡哨的也很多,但是简单使用的很少。

在很多实际项目中只要用到demo代码中的最普通的显示文本的情况就ok的,需要显示图片的场景并不多。

并且上面显示图片类型的代码,都是添加了不同动画类的,移植反而麻烦。

所以一般的使用只移植简单文本部分的功能使用就OK了。

其他的就当预留的吧,万一真的要呢。

如果对话框UI没啥要求,只要可以显示文本和确定、取消按钮这样的场景,使用原生的AlertDialog很好了。

2、Android对话框的使用总结

都是对原生对话框的详细介绍

https://blog.csdn.net/wenzhi20102321/article/details/52818351

3、Android加载中对话框示例

转圈圈的加载中对话框

https://blog.csdn.net/wenzhi20102321/article/details/79619719

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值