android 自定义时间对话框,Android自定义等待对话框

最近,看了好多的APP的等待对话框,发现自己的太lower,于是就研究了一番,最后经过苦心努力,实现一个。

自定义一个LoadingIndicatorView(extends View )类

编写values/attrs.xml,在其中编写styleable和item等标签元素

在布局文件中LoadingIndicatorView使用自定义的属性(注意namespace)

在LoadingIndicatorView的构造方法中通过TypedArray获取

描述就提供这些,一下是代码的展示,非常的详细。

1、自定义属性的声明文件

 
 

LoadingIndicatorView.java

import android.annotation.TargetApi;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.os.Build;

import android.support.annotation.IntDef;

import android.util.AttributeSet;

import android.view.View;

import com.chni.lidong.androidtestdemo.R;

/**

* Created by lidongon 2016/1/31

*

.BallSpinFadeLoader,

*

*/

public class LoadingIndicatorView extends View {

//indicators 指示器

public static final int BallSpinFadeLoader=22;

@IntDef(flag = true,

value = {

BallSpinFadeLoader,

})

public @interface Indicator{}

//Sizes (with defaults in DP)

public static final int DEFAULT_SIZE=45;

//attrs

int mIndicatorId;

int mIndicatorColor;

Paint mPaint;

BaseIndicatorController mIndicatorController;

private boolean mHasAnimation;

public LoadingIndicatorView(Context context) {

super(context);

init(null, 0);

}

public LoadingIndicatorView(Context context, AttributeSet attrs) {

super(context, attrs);

init(attrs, 0);

}

public LoadingIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(attrs, defStyleAttr);

}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

public LoadingIndicatorView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

init(attrs, defStyleAttr);

}

private void init(AttributeSet attrs, int defStyle) {

/**

*获取TypedArray(属性的集合)

*/

TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AVLoadingIndicatorView);

mIndicatorId=a.getInt(R.styleable.AVLoadingIndicatorView_indicator, BallSpinFadeLoader);//获取编号属性

mIndicatorColor=a.getColor(R.styleable.AVLoadingIndicatorView_indicator_color, Color.WHITE);//获取颜色属性

a.recycle();//回收属性的集合

mPaint=new Paint();

mPaint.setColor(mIndicatorColor);//设置画笔的颜色

mPaint.setStyle(Paint.Style.FILL);//设置画笔的样式为填充

mPaint.setAntiAlias(true);//去锯齿

applyIndicator();//

}

private void applyIndicator(){

switch (mIndicatorId){

case BallSpinFadeLoader:

mIndicatorController=new BallSpinFadeLoaderIndicator();

break;

}

mIndicatorController.setTarget(this);//将控件设置到当前View

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int width = measureDimension(dp2px(DEFAULT_SIZE), widthMeasureSpec);//获取View的宽度

int height = measureDimension(dp2px(DEFAULT_SIZE), heightMeasureSpec);//获取View的高度

setMeasuredDimension(width, height);//

}

/**

*测量的 维度

* @param defaultSize 默认大小

* @param measureSpec {@see widthMeasureSpec,heightMeasureSpec}

* @return 返回测量的结果

*/

private int measureDimension(int defaultSize,int measureSpec){

int result = defaultSize;

int specMode = MeasureSpec.getMode(measureSpec);//测量规范

int specSize = MeasureSpec.getSize(measureSpec);//测量大小

if (specMode == MeasureSpec.EXACTLY) {//父控件已经为子控件设置确定的大小,子控件会考虑父控件给他的大小,自己需要多大设置多大

result = specSize;

} else if (specMode == MeasureSpec.AT_MOST) {//子控件可以设置自己希望的指定大小

result = Math.min(defaultSize, specSize);//取最小值

} else {

result = defaultSize;

}

return result;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawIndicator(canvas);

}

@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

if (!mHasAnimation){

mHasAnimation=true;

applyAnimation();

}

}

void drawIndicator(Canvas canvas){

mIndicatorController.draw(canvas,mPaint);

}

void applyAnimation(){

mIndicatorController.createAnimation();

}

private int dp2px(int dpValue) {

return (int) getContext().getResources().getDisplayMetrics().density * dpValue;

}

BaseIndicatorController.java

package com.chni.lidong.androidtestdemo.loading;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.view.View;

/**

* Created by lidongon 2016/1/31

*/

public abstract class BaseIndicatorController {

private View mTarget;

public void setTarget(View target){

this.mTarget=target;

}

public View getTarget(){

return mTarget;

}

/**

* 得到View的宽度

* @return

*/

public int getWidth(){

return mTarget.getWidth();

}

/**

* 得到view的高度

* @return

*/

public int getHeight(){

return mTarget.getHeight();

}

/**

* 刷新view

*/

public void postInvalidate(){

mTarget.postInvalidate();

}

/**

* draw indicator what ever

* you want to draw

* 绘制indicate

* @param canvas

* @param paint

*/

public abstract void draw(Canvas canvas,Paint paint);

/**

* create animation or animations

* ,and add to your indicator.

* 创建动画或者动画集合,添加到indcator

*/

public abstract void createAnimation();

}

BallSpinFadeLoaderIndicator.java

package com.chni.lidong.androidtestdemo.loading;

import android.graphics.Canvas;

import android.graphics.Paint;

import com.nineoldandroids.animation.ValueAnimator;

/**

* Created by lidongon 2016/1/31

*/

public class BallSpinFadeLoaderIndicator extends BaseIndicatorController {

public static final float SCALE=1.0f;

public static final int ALPHA=255;

/**

* 圆点的比例

*/

float[] scaleFloats=new float[]{SCALE,

SCALE,

SCALE,

SCALE,

SCALE,

SCALE,

SCALE,

SCALE};

/**

* 圆点的透明度集合

*/

int[] alphas=new int[]{ALPHA,

ALPHA,

ALPHA,

ALPHA,

ALPHA,

ALPHA,

ALPHA,

ALPHA};

@Override

public void draw(Canvas canvas, Paint paint) {

float radius=getWidth()/10;

for (int i = 0; i < 8; i++) {

canvas.save();

Point point=circleAt(getWidth(),getHeight(),getWidth()/2-radius,i*(Math.PI/4));

canvas.translate(point.x,point.y);

canvas.scale(scaleFloats[i],scaleFloats[i]);

paint.setAlpha(alphas[i]);

canvas.drawCircle(0,0,radius,paint);

canvas.restore();

}

}

/**

* 圆O的圆心为(a,b),半径为R,点A与到X轴的为角α.

*则点A的坐标为(a+R*cosα,b+R*sinα)

* @param width

* @param height

* @param radius

* @param angle

* @return

*/

Point circleAt(int width,int height,float radius,double angle){

float x= (float) (width/2+radius*(Math.cos(angle)));

float y= (float) (height/2+radius*(Math.sin(angle)));

return new Point(x,y);

}

@Override

public void createAnimation() {

int[] delays= {0, 120, 240, 360, 480, 600, 720, 780, 840};

for (int i = 0; i < 8; i++) {

final int index=i;

ValueAnimator scaleAnim=ValueAnimator.ofFloat(1,0.4f,1);//创建ValueAnimator对象

scaleAnim.setDuration(1000);//设置动画的持续时间

scaleAnim.setRepeatCount(-1);//设置动画是否重复

scaleAnim.setStartDelay(delays[i]);//延迟启动动画

scaleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//ValueAnimator只负责第一次的内容,因此必须通过监听来实现对象的相关属性的更新

@Override

public void onAnimationUpdate(ValueAnimator animation) {

scaleFloats[index] = (float) animation.getAnimatedValue();//获取当前帧的值

postInvalidate();

}

});

scaleAnim.start();//启动属性动画

ValueAnimator alphaAnim=ValueAnimator.ofInt(255, 77, 255);//透明度动画

alphaAnim.setDuration(1000);//

alphaAnim.setRepeatCount(-1);

alphaAnim.setStartDelay(delays[i]);

alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

alphas[index] = (int) animation.getAnimatedValue();

postInvalidate();

}

});

alphaAnim.start();

}

}

final class Point{

public float x;

public float y;

public Point(float x, float y){

this.x=x;

this.y=y;

}

}

}

UIHelp.java

package com.chni.lidong.androidtestdemo.utils;

import android.app.Activity;

import android.app.Dialog;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.LinearLayout;

import android.widget.TextView;

import com.chni.lidong.androidtestdemo.R;

/**

* 对话框的实现

* @author 李东

* @Date 2014-11-23

*/

public class UIHelper {

/** 加载数据对话框 */

private static Dialog mLoadingDialog;

/**

* 显示加载对话框

* @param context 上下文

* @param msg 对话框显示内容

* @param cancelable 对话框是否可以取消

*/

public static void showDialogForLoading(Activity context, String msg, boolean cancelable) {

View view = LayoutInflater.from(context).inflate(R.layout.layout_loading_dialog, null);

TextView loadingText = (TextView)view.findViewById(R.id.id_tv_loading_dialog_text);

loadingText.setText(msg);

mLoadingDialog = new Dialog(context, R.style.loading_dialog_style);

mLoadingDialog.setCancelable(cancelable);

mLoadingDialog.setContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));

mLoadingDialog.show();

}

/**

* 关闭加载对话框

*/

public static void hideDialogForLoading() {

if(mLoadingDialog != null && mLoadingDialog.isShowing()) {

mLoadingDialog.cancel();

}

}

}

对话框的布局:

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@drawable/bg_loading_dialog_shape"

android:gravity="center"

android:minHeight="60dp"

android:minWidth="180dp"

android:orientation="vertical"

android:padding="@dimen/padding_10" >

android:layout_width="wrap_content"

android:layout_weight="1"

android:gravity="center"

android:layout_height="wrap_content">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:indicator="BallSpinFadeLoader"

app:indicator_color="@color/green"

/>

android:id="@+id/id_tv_loading_dialog_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="@dimen/padding_5"

android:text="正在登录…"

android:textColor="@color/content"

android:textSize="14sp" />

对话框的样式:

@null

true

@color/transparent

true

@null

MainActivity.java

public class Main7Activity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main7);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);

fab.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)

.setAction("Action", null).show();

}

});

UIHelper.showDialogForLoading(this, "正在加载...", true);

Handler handler = new Handler();

handler.postDelayed(new Runnable() {

@Override

public void run() {

UIHelper.hideDialogForLoading();

}

},10000);

}

}

效果图;

e111d974fd5f9c79f2ff394101bc63dd.png

以上就是本文的全部内容,希望对大家的学习有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值