[Android] 仿IOS实现自定义Dialog,底部弹窗和中间弹窗工具

本文详细介绍了如何在Android中实现仿IOS风格的自定义Dialog,包括底部弹窗和中间弹窗,并提供了核心代码、布局文件、动画效果及使用示例。通过自定义,可以实现丰富的样式和细节调整,便于开发者快速应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用过Android的默认对话框的都懂,不管是哪个版本的对话框,都丑到爆!就算是Google推崇的Material Design风格的弹窗一样不好看,基本每款APP都不会去使用默认的对话框样式,他们都有自己的风格,怎样去改变默认的对话框样式呢?只能自定义了,将系统对话框改为自己喜欢或者是APP特有风格的样式。本文将介绍如何去实现自定义Dialog,仿IOS,并添加动画效果,并提供丰富的方法调用,让开发者可以在已有样式的基础上进行进一步的细节改变。算是一个工具类了,直接copy就可以直接用了。

原创文章,转载请注明出处:https://blog.youkuaiyun.com/Lone1yCode/article/details/79927873

一、举例

这是Android 4.2版本的弹窗:


这是Android 7.0版本的弹窗:


我是没有觉得很好看。大概这就是程序员的审美吧。

下面再看一下IOS的对话框,话说找这个对话框太难了。我找了好久好久,都找不到有什么地方能弹窗,不找的时候一直有。还好不负所望,找了俩。中间弹窗对话框:


IOS底部弹窗:


是不是感觉还不错!Android的系统对话框虽然样式很丑,但毕竟是开源系统,它可以轻松实现对话框样式的自定义,而且Android的对话框的样式基本一个APP就一个样,种类繁多,样式丰富。

二、实现效果

经过自定义后,现在的Dialog已经能实现各种丰富的样式了。


可以看到自定义的Dialog已经实现了IOS效果的弹窗。并且里面的按钮、文本、标题都可以在使用时进行各种详细的定义,如改变文字颜色、文字大小、文字粗体、背景色,还可以传入自己定义的动画效果去替换原有的动画效果,如果不觉得突兀,还可以取消动画效果

三、特点

其实特点就是仿照IOS的特点。

1、圆角。经过自定义的弹窗,其圆角效果已经和IOS的很接近了,而且圆角很大,当然如果你不喜欢,可以在XML文件中进行修改,目前的圆角是15。

2、Dialog控件之间的间隔很大。这应该也算是IOS风格的一个特色了,它的文字、留白都非常大,如果说多数Android的弹窗效果都是小巧玲珑的话,这种风格可以说是豪迈奔放了。

3、动画效果。这个动画效果是完全仿IOS的,底部弹窗效果不是很像,只是加了一个平移效果。中间弹窗的话还能算是精仿,包括缩放和透明度的变化。

四、全部代码

说实话,全部代码并不长,只是注释太多,占用了绝大部分的空间。

1、MyDialog核心类

package com.my.dialogdemo;

import android.app.Dialog;
import android.content.Context;
import android.support.v7.app.ActionBar;
import android.text.TextPaint;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static android.content.ContentValues.TAG;

public class MyDialog {

    private Context mContext;                       //上下文

    private View mDialogLayout;                     //弹窗布局

    private boolean mCancelable = true;             //返回键、窗体外区域是否可点击取消,默认可以

    private View.OnClickListener positiveButton;    //positive区域监听器
    private View.OnClickListener negativeButton;    //negative区域监听器

    private AdapterView.OnItemClickListener mItemClickListener;  //item的点击事件

    private Dialog dialog;                          //构建的弹窗

    private int mCustomAnim;                        //自定义动画

    private boolean mIsShowTitle;                   //是否显示标题,默认不显示
    private boolean mIsShowNegativeButton;          //是否显示negative区域按钮,默认不显示
    private boolean mIsShowPositiveButton;          //是否显示positive区域按钮,默认不显示
    private boolean mIsShowListView;                //是否在内容区显示ListView,默认不显示
    private boolean mIsHaveCustomAnim;              //是否含有自定义的动画效果

    private boolean mIsShowBottomTitle;             //是否显示底部弹窗标题,默认不显示
    private boolean mIsShowBottomNegativeButton;    //是否显示底部弹窗的negative区域按钮,默认不显示
    private boolean mIsBottomDialog;                //是否是底部弹窗,默认中间弹窗

    private MyAdapter mAdapter;                     //Adapter,设配自定义的数据
    private List<StringItemBean> mDataList;         //数据源,显示的文本

    public static final String BOTTOM = "BOTTOM";   //底部弹窗标志

    /**
     * 中间弹窗,构造函数
     *
     * @param context 上下文
     */
    public MyDialog(Context context) {
        this.mContext = context;
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mDialogLayout = inflater.inflate(R.layout.my_custom_dialog_layout, null);
    }

    /**
     * 中间弹窗,构造函数,需要传入自定义动画的ID,若传入0,则代表无动画
     *
     * @param context    上下文
     * @param customAnim 自定义的动画效果ID
     */
    public MyDialog(Context context, int customAnim) {
        this(context);
        mCustomAnim = customAnim;
        mIsHaveCustomAnim = true;
    }

    /**
     * 底部弹窗,构造函数,需要传入String类型参数,BOTTOM,才会显示底部Dialog
     *
     * @param context 上下文
     * @param gravity 位置,String类型,必须是"BOTTOM"才会显示底部Dialog
     */
    public MyDialog(Context context, String gravity) {
        this.mContext = context;
        if (gravity.equals(BOTTOM)) {
            mIsBottomDialog = true;
        }
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mDialogLayout = inflater.inflate(R.layout.my_custom_bottom_dialog_layout, null);
    }

    /**
     * 都不弹窗,构造函数,需要传入String类型参数,BOTTOM,才会显示底部Dialog;自定义动画效果
     *
     * @param context    上下文
     * @param customAnim 自定义的动画效果
     * @param gravity    位置,String类型,必须是"BOTTOM"才会显示底部Dialog
     */
    public MyDialog(Context context, int customAnim, String gravity) {
        this.mContext = context;
        if (gravity.equals(BOTTOM)) {
            mIsBottomDialog = true;
        }
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mDialogLayout = inflater.inflate(R.layout.my_custom_bottom_dialog_layout, null);
        mCustomAnim = customAnim;
        mIsHaveCustomAnim = true;
    }

    /**
     * 能否返回键取消和点击弹窗外部区域取消
     * 中间、底部弹窗共用
     *
     * @param boolean1 true 代表可以取消,false 不可取消
     * @return this
     */
    public MyDialog setCancelable(Boolean boolean1) {
        this.mCancelable = boolean1;
        return this;
    }

    /**
     * 中间弹窗,设置标题 int型 不常用,适配更多类型可重载多个该方法,参数类型不同即可
     *
     * @param title int型参数
     * @return this
     */
    public MyDialog setTitle(int title) {
        mIsShowTitle = true;
        ((TextView) mDialogLayout.findViewById(R.id.title)).setText(title);
        return this;
    }

    /**
     * 中间弹窗,设置标题 String型 最常用
     *
     * @param title String型参数
     * @return this
     */
    public MyDialog setTitle(String title) {
        mIsShowTitle = true;
        ((TextView) mDialogLayout.findViewById(R.id.title)).setText(title);
        return this;
    }

    /**
     * 中间弹窗,设置标题文字大小
     *
     * @param size 大小值,int型
     * @return this
     */
    public MyDialog setTitleSize(int size) {
        ((TextView) mDialogLayout.findViewById(R.id.title)).setTextSize(size);
        return this;
    }

    /**
     * 中间弹窗,设置标题文字颜色
     *
     * @param color 颜色
     * @return this
     */
    public MyDialog setTitleColor(int color) {
        ((TextView) mDialogLayout.findViewById(R.id.title)).setTextColor(mContext.getResources().getColor(color));
        return this;
    }

    /**
     * 中间弹窗,设置标题字体为粗体
     *
     * @return this
     */
    public MyDialog setTitleStyleBold(){
        TextView tv = (TextView)mDialogLayout.findViewById(R.id.title);
        TextPaint tp = tv.getPaint();
        tp.setFakeBoldText(true);
        return this;
    }

    /**
     * 中间弹窗,设置标题区域的背景颜色 不常用
     *
     * @param color 颜色
     * @return this
     */
    public MyDialog setTitleBackgroundColor(int color) {
        mDialogLayout.findViewById(R.id.title_background).setBackgroundColor(mContext.getResources().getColor(color));
        return this;
    }

    /**
     * 中间弹窗,设置内容,int型,不常用,适配更多类型可重载多个该方法,参数类型不同即可
     *
     * @param message int型参数
     * @return this
     */
    public MyDialog setMessage(int message) {
        ((TextView) mDialogLayout.findViewById(R.id.message)).setText(message);
        return this;
    }

    /**
     * 中间弹窗,设置内容,String型,最常用
     *
     * @param message String型信息
     * @return this
     */
    public MyDialog setMessage(String message) {
        ((TextView) mDialogLayout.findViewById(R.id.message)).setText(message);
        return this;
    }

    /**
     * 中间弹窗,设置内容的文本颜色
     *
     * @param color 文本颜色
     * @return this
     */
    public MyDialog setMessageColor(int color){
        ((TextView) mDialogLayout.findViewById(R.id.message)).setTextColor(
                mContext.getResources().getColor(color));
        return this;
    }

    /**
     * 中间弹窗,设置内容区域的背景色
     *
     * @param color 背景色
     * @return this
     */
    public MyDialog setMessageBackground(int color){
        mDialogLayout.findViewById(R.id.content).setBackgroundColor(
                mContext.getResources().getColor(color));
        return this;
    }

    /**
     * 中间弹窗,设置negative区域的文本和点击事件,一般为"取消"
     * 同AlertDialog.Builder的设置名称相同
     *
     * @param negativeText 按钮文本
     * @param listener     监听器
     * @return this
     */
    public MyDialog setNegativeButton(String negativeText, View.OnClickListener listener) {
        mIsShowNegativeButton = true;
        ((TextView) mDialogLayout.findViewById(R.id.negative)).setText(negativeText);
        this.negativeButton = listener;
        return this;
    }

    /**
     * 中间弹窗,设置negative区域显示文本的颜色,如蓝色的"取消"文字
     * 多数APP如网购APP,在某个商品浏览页面,不希望用户退出又必须要给出退出提示时,多将negative设置为显眼的颜色
     * 而positive设置为暗色。所以该方法还是使用比较常见的
     *
     * @param color 颜色
     * @return this
     */
    public MyDialog setNegativeButtonColor(int color) {
        ((TextView) mDialogLayout.findViewById(R.id.negative)).setTextColor(
                mContext.getResources().getColor(color));
        return this;
    }

    /**
     * 中间弹窗,设置negative文本的大小
     *
     * @param size 文本大小
     * @return this
     */
    public MyDialog setNegativeButtonTextSize(int size){
        ((TextView) mDialogLayout.findViewById(R.id.negative)).setTextSize(size);
        return this;
    }

    /**
     * 中间弹窗,设置negative文本字体为粗体
     *
     * @return this
     */
    public MyDialog setNegativeButtonStyleBold(){
        TextView tv = (TextView) mDialogLayout.findViewById(R.id.negative);
        TextPaint tp = tv.getPaint();
        tp.setFakeBoldText(true);
        return this;
    }

    /**
     * 中间弹窗,设置positive区域的文本和点击事件,一般为"确定"
     * 同AlertDialog.Builder的设置名称相同
     *
     * @param positiveText 按钮文本
     * @param listener     监听器
     * @return this
     */
    public MyDialog setPositiveButton(String positiveText, View.OnClickListener listener) {
        mIsShowPositiveButton = true;
        ((TextView) mDialogLayout.findViewById(R.id.positive)).setText(positiveText);
        this.positiveButton = listener;
        return this;
    }

    /**
     * 中间弹窗,设置positive区域显示文本的颜色,如蓝色的"确定"文字
     *
     * @param color 颜色
     * @return this
     */
    public MyDialog setPositiveButtonColor(int color) {
        ((TextView) mDialogLayout.findViewById(R.id.positive)).setTextColor(
                mContext.getResources().getColor(color));
        return this;
    }

    /**
     * 中间弹窗,设置positive区域显示文本的大小
     *
     * @param size 文本大小
     * @return this
     */
    public MyDialog setPositiveButtonSize(int size){
        ((TextView) mDialogLayout.findViewById(R.id.positive)).setTextSize(size);
        return this;
    }

    /**
     * 中间弹窗,设置positive文本字体为粗体
     *
     * @return this
     */
    public MyDialog setPositiveButtonStyleBold(){
        TextView tv = (TextView) mDialogLayout.findViewById(R.id.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值