Android (sweet-dialog)听名字就很甜!!!

本文介绍了一个美观且兼容性良好的Dialog框架——SweetDialog。该框架通过自定义View实现了多种类型的提示框,并提供了详细的实现原理和代码示例。

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

前言: 由于以前接触过太多的控件,做过太多的项目,因为之前在外包,所以一直没时间去整理自己用过的一些工具跟第三方的东西,也没有真正地去研究过一个一个东西,现在终于挤出一点时间来整理下以前做过的东西了,今天要给大家分享的是以前在github上面看到的一个Dialog框架,叫sweetdialog,真的很漂亮哈!!!并且能够兼容3.0一下的手机,是不是很棒呢?
先贴出其github上的链接(感谢这位仁兄):
https://github.com/pedant/sweet-alert-dialog

然后上一张效果图:

这里写图片描述

怎么样?是不是效果还不错哦?当然,小伙伴可以自己改改其中的布局跟颜色,换成自己想要的效果!!
下面说说其实现的方式:
首先也是继承Dialog,然后设置dialog的样式:

public class SweetAlertDialog extends Dialog

设置dialog样式:

public SweetAlertDialog(Context context, int alertType) {
        super(context, R.style.alert_dialog);

R.style.alert_dialog(Dialog默认style):

 <style name="alert_dialog" parent="android:Theme.Dialog">
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">false</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">false</item>
        <item name="android:windowBackground">@color/float_transparent</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:backgroundDimAmount">0.4</item>
    </style>

这些属性不了解的话,可以去看我的另外一篇博客:
Android进阶之(Dailog详解)
然后在dialog的oncreate方法中去设置Dialog的contentView:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.alert_dialog);

alert_dialog.layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:wheel="http://schemas.android.com/apk/res-auto"
    android:id="@+id/loading"
    android:layout_width="@dimen/alert_width"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:background="@drawable/dialog_background"
    android:padding="10dp">

    <ImageView
        android:id="@+id/custom_image"
        android:layout_width="53dp"
        android:layout_height="53dp"
        android:layout_marginTop="5dp"
        android:contentDescription="@string/app_name"
        android:visibility="gone"
        android:scaleType="fitCenter" />

    <FrameLayout
        android:id="@+id/error_frame"
        android:layout_width="53dp"
        android:layout_height="53dp"
        android:layout_marginTop="5dp"
        android:visibility="gone">
        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/error_circle" />

        <ImageView
            android:id="@+id/error_x"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/app_name"
            android:src="@drawable/error_center_x"
            android:scaleType="center" />

    </FrameLayout>

    <FrameLayout
        android:id="@+id/success_frame"
        android:layout_width="53dp"
        android:layout_height="53dp"
        android:layout_marginTop="5dp"
        android:visibility="gone">

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/success_bow" />

        <View
            android:id="@+id/mask_right"
            android:layout_width="35dp"
            android:layout_height="80dp"
            android:layout_marginTop="-13dp"
            android:layout_gravity="right"
            android:background="@android:color/white" />

        <View
            android:id="@+id/mask_left"
            android:layout_width="21dp"
            android:layout_height="60dp"
            android:layout_marginLeft="-3dp"
            android:layout_gravity="left"
            android:background="@android:color/white" />

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/success_circle" />

        <com.cisetech.demo.sweetdialog.SuccessTickView
            android:id="@+id/success_tick"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>

    <FrameLayout
        android:id="@+id/warning_frame"
        android:layout_width="53dp"
        android:layout_height="53dp"
        android:layout_marginTop="5dp"
        android:visibility="gone">

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/warning_circle" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/app_name"
            android:src="@drawable/warning_sigh"
            android:scaleType="center" />
    </FrameLayout>

    <FrameLayout
        android:id="@+id/progress_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="9dp"
        android:layout_gravity="center"
        android:orientation="vertical"
        android:visibility="gone">

        <com.cisetech.demo.ProgressWheel
            android:id="@+id/progressWheel"
            android:layout_width="80dp"
            android:layout_height="80dp"
            wheel:pwBarColor="@color/blue_btn_bg_pressed_color"
            wheel:pwBarLength="40dp"
            wheel:pwBarWidth="2dp"
            wheel:pwRimColor="#FFF8F8"
            wheel:pwRimWidth="2dp"
            wheel:pwSpinSpeed="4dp"
            wheel:pwTextColor="#FFF8F8"
            android:layout_gravity="center" />
    </FrameLayout>

    <TextView
        android:id="@+id/title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="19sp"
        android:textColor="#575757"
        android:layout_marginTop="10dp"
        android:singleLine="true"
        android:text="@string/dialog_default_title" />

    <TextView
        android:id="@+id/content_text"
        android:layout_marginTop="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textAlignment="center"
        android:gravity="center"
        android:textColor="#797979"
        android:visibility="gone" />

    <LinearLayout
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">

        <Button
            android:id="@+id/cancel_button"
            style="@style/dialog_blue_button"
            android:background="@drawable/gray_button_background"
            android:layout_marginRight="10dp"
            android:visibility="gone"
            android:text="@string/dialog_cancel" />

        <Button
            android:id="@+id/confirm_button"
            style="@style/dialog_blue_button"
            android:text="@string/dialog_ok" />
    </LinearLayout>
</LinearLayout>

alert_dialog.xml主要分为:
这里写图片描述

 mCustomImage.setVisibility(View.GONE);
        mErrorFrame.setVisibility(View.GONE);
        mSuccessFrame.setVisibility(View.GONE);
        mWarningFrame.setVisibility(View.GONE);
        mProgressFrame.setVisibility(View.GONE);

布局还是很清楚的,切换dialog的时候,只需要隐藏其他几个布局,显示指定的布局即可,相信大家都可以实现哦。

1、我现在隐藏掉其它所有的view,显示出custom_image:
这里写图片描述

是不是跟我们一开始演示的gif图片中的效果一样咯?
2、我现在隐藏掉其它所有的view,显示出error_frame:
这里写图片描述

剩下的我就不演示了,看到这里我们是不是了解了切换Dialog的原理的呢?我们看看代码的处理:
首先隐藏掉所有的View:

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

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

然后显示出需要显示的View

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;
                case PROGRESS_TYPE:
                    mProgressFrame.setVisibility(View.VISIBLE);
                    mConfirmButton.setVisibility(View.GONE);
                    break;
            }
            if (!fromCreate) {
                playAnimation();
            }
        }
    }

sweetdialog牛逼点的地方布置是设置好看,而且其中成功、错误、警告、三种方式的Diailog的icon居然是用的自定义view画出来的,厉害了我的哥,我一开始以为是导的图片,,唉唉~~太年轻啊

我们先看看SuccessDialog中的那个“√”标记的实现:
这里写图片描述

package com.cisetech.demo.sweetdialog;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import com.cisetech.demo.R;


public class SuccessTickView extends View {
    /**
     * 屏幕像素密度
     */
    private float mDensity = -1;
    private Paint mPaint;
    /**
     * 圆角的半径
     */
    private final float CONST_RADIUS = dip2px(1.2f);
    /**
     *
     */
    private final float CONST_RECT_WEIGHT = dip2px(3);
    private final float CONST_LEFT_RECT_W = dip2px(15);
    private final float CONST_RIGHT_RECT_W = dip2px(25);
    private final float MIN_LEFT_RECT_W = dip2px(3.3f);
    private final float MAX_RIGHT_RECT_W = CONST_RIGHT_RECT_W + dip2px(6.7f);

    private float mMaxLeftRectWidth;
    private float mLeftRectWidth;
    private float mRightRectWidth;
    private boolean mLeftRectGrowMode;

    public SuccessTickView(Context context) {
        super(context);
        init();
    }

    public SuccessTickView(Context context, AttributeSet attrs){
        super(context,attrs);
        init();
    }

    private void init () {
        mPaint = new Paint();
        mPaint.setColor(getResources().getColor(R.color.success_stroke_color));
        mLeftRectWidth = CONST_LEFT_RECT_W;
        mRightRectWidth = CONST_RIGHT_RECT_W;
        mLeftRectGrowMode = false;
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        int totalW = getWidth();
        int totalH = getHeight();
        // rotate canvas first
        canvas.rotate(45, totalW/2, totalH/2);

        totalW /= 1.2;
        totalH /= 1.4;
        mMaxLeftRectWidth = (totalW + CONST_LEFT_RECT_W) / 2 + CONST_RECT_WEIGHT - 1;

        RectF leftRect = new RectF();
        if (mLeftRectGrowMode) {
            leftRect.left = 0;
            leftRect.right = leftRect.left + mLeftRectWidth;
            leftRect.top = (totalH + CONST_RIGHT_RECT_W) / 2;
            leftRect.bottom = leftRect.top + CONST_RECT_WEIGHT;
        } else {
            leftRect.right = (totalW + CONST_LEFT_RECT_W) / 2 + CONST_RECT_WEIGHT - 1;
            leftRect.left = leftRect.right - mLeftRectWidth;
            leftRect.top = (totalH + CONST_RIGHT_RECT_W) / 2;
            leftRect.bottom = leftRect.top + CONST_RECT_WEIGHT;
        }

        canvas.drawRoundRect(leftRect, CONST_RADIUS, CONST_RADIUS, mPaint);

        RectF rightRect = new RectF();
        rightRect.bottom = (totalH + CONST_RIGHT_RECT_W) / 2 + CONST_RECT_WEIGHT - 1;
        rightRect.left = (totalW + CONST_LEFT_RECT_W) / 2;
        rightRect.right = rightRect.left + CONST_RECT_WEIGHT;
        rightRect.top = rightRect.bottom - mRightRectWidth;
        canvas.drawRoundRect(rightRect, CONST_RADIUS, CONST_RADIUS, mPaint);
    }

    public float dip2px(float dpValue) {
        if(mDensity == -1) {
            mDensity = getResources().getDisplayMetrics().density;
        }
        return dpValue * mDensity + 0.5f;
    }

    public void startTickAnim () {
        // hide tick
        mLeftRectWidth = 0;
        mRightRectWidth = 0;
        invalidate();
        Animation tickAnim = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                super.applyTransformation(interpolatedTime, t);
                if (0.54 < interpolatedTime && 0.7 >= interpolatedTime) {  // grow left and right rect to right
                    mLeftRectGrowMode = true;
                    mLeftRectWidth = mMaxLeftRectWidth * ((interpolatedTime - 0.54f) / 0.16f);
                    if (0.65 < interpolatedTime) {
                        mRightRectWidth = MAX_RIGHT_RECT_W * ((interpolatedTime - 0.65f) / 0.19f);
                    }
                    invalidate();
                } else if (0.7 < interpolatedTime && 0.84 >= interpolatedTime) { // shorten left rect from right, still grow right rect
                    mLeftRectGrowMode = false;
                    mLeftRectWidth = mMaxLeftRectWidth * (1 - ((interpolatedTime - 0.7f) / 0.14f));
                    mLeftRectWidth = mLeftRectWidth < MIN_LEFT_RECT_W ? MIN_LEFT_RECT_W : mLeftRectWidth;
                    mRightRectWidth = MAX_RIGHT_RECT_W * ((interpolatedTime - 0.65f) / 0.19f);
                    invalidate();
                } else if (0.84 < interpolatedTime && 1 >= interpolatedTime) { // restore left rect width, shorten right rect to const
                    mLeftRectGrowMode = false;
                    mLeftRectWidth = MIN_LEFT_RECT_W + (CONST_LEFT_RECT_W - MIN_LEFT_RECT_W) * ((interpolatedTime - 0.84f) / 0.16f);
                    mRightRectWidth = CONST_RIGHT_RECT_W + (MAX_RIGHT_RECT_W - CONST_RIGHT_RECT_W) * (1 - ((interpolatedTime - 0.84f) / 0.16f));
                    invalidate();
                }
            }
        };
        tickAnim.setDuration(750);
        tickAnim.setStartOffset(100);
        startAnimation(tickAnim);
    }
}

这里写图片描述

然后就是给一个动画来实现其绘画的轨迹了。

下面看看error_frame:

 <FrameLayout
        android:id="@+id/error_frame"
        android:layout_width="53dp"
        android:layout_height="53dp"
        android:layout_marginTop="5dp"
        android:visibility="visible">
        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/error_circle" />

        <ImageView
            android:id="@+id/error_x"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/app_name"
            android:src="@drawable/error_center_x"
            android:scaleType="center" />

    </FrameLayout>

先画一个圈:

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/transparent" />
    <stroke android:color="@color/error_stroke_color" android:width="@dimen/common_circle_width" />
</shape>

然后画两条线,再把两条线旋转下角度:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate android:fromDegrees="45" android:toDegrees="45" android:pivotX="50%" android:pivotY="50%">
            <shape android:shape="rectangle">
                <solid android:color="@color/error_stroke_color"/>
                <corners android:radius="4dp"/>
                <size android:height="3dp" android:width="28dp"/>
            </shape>
        </rotate>
    </item>

    <item>
        <rotate android:fromDegrees="315" android:toDegrees="315" android:pivotX="50%" android:pivotY="50%">
            <shape android:shape="rectangle">
                <solid android:color="@color/error_stroke_color"/>
                <corners android:radius="4dp"/>
                <size android:height="3dp" android:width="28dp"/>
            </shape>
        </rotate>
    </item>
</layer-list>

这里写图片描述

在as上我们看的很清楚,是不是有点佩服这位仁兄了,要是我做的话,就用图片了,哈哈~~~~

最后看一下warning_frame(跟erro的实现方式差不多):

<FrameLayout
        android:id="@+id/warning_frame"
        android:layout_width="53dp"
        android:layout_height="53dp"
        android:layout_marginTop="5dp"
        android:visibility="visible">

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/warning_circle" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/app_name"
            android:src="@drawable/warning_sigh"
            android:scaleType="center" />
    </FrameLayout>

这里写图片描述

warning_sigh.drawable文件:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:bottom="8dp" android:left="1dp" android:right="1dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/warning_stroke_color"/>
            <corners android:radius="4dp"/>
            <size android:height="22dp" android:width="3dp"/>
        </shape>
    </item>

    <item android:top="30dp">
        <shape android:shape="oval">
            <solid android:color="@color/warning_stroke_color"/>
            <size android:height="5dp" android:width="4dp"/>
        </shape>
    </item>
</layer-list>

这里写图片描述

好啦!!SweetDialog就讲到这里了,还有动画部分没讲,要研究的童鞋自己看源码啊。
最后奉上我的demo的github链接:
https://github.com/913453448/DialogDemoSweet

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值