前言: 由于以前接触过太多的控件,做过太多的项目,因为之前在外包,所以一直没时间去整理自己用过的一些工具跟第三方的东西,也没有真正地去研究过一个一个东西,现在终于挤出一点时间来整理下以前做过的东西了,今天要给大家分享的是以前在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