博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 的自定义等待对话框
阅读量:5752 次
发布时间:2019-06-18

本文共 11236 字,大约阅读时间需要 37 分钟。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010046908/article/details/50614383

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

  1. 自定义一个LoadingIndicatorView(extends View )类
  2. 编写values/attrs.xml,在其中编写styleable和item等标签元素
  3. 在布局文件中LoadingIndicatorView使用自定义的属性(注意namespace)
  4. 在LoadingIndicatorView的构造方法中通过TypedArray获取
   描述就提供这些,一下是代码的展示,非常的详细。
  • 自定义属性的声明文件
 
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();		}	}}

对话框的布局:

对话框的样式:

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);    }}
最终的截图:

你可能感兴趣的文章
同质化倾向的互联网金融 玖富带来了温度与色彩
查看>>
SCCM的证书配置PKI
查看>>
看linux书籍做的一些重要笔记(2011.07.03更新)
查看>>
Exchange server 2010系列教程之一 安装Exchange 2010准备条件
查看>>
POI 生成 xls 文件使用总结(快速入门)
查看>>
CString、Char* ,char [20]、wchar_t、unsigned short转化
查看>>
从案例学RxAndroid开发(上)
查看>>
debian 下安装megacli
查看>>
我写的第一个shell脚本(2009-06-08)
查看>>
ubutun 中 Eclipse中 快捷键 Alt + / 不能使用的问题
查看>>
Redis学习手册(内存优化)
查看>>
浅尝TensorFlow on Kubernetes
查看>>
wnmp-3.1.0安装cakephp启动失败处理
查看>>
springboot系列十 Spring-Data-Redis
查看>>
Confluence 6 注册外部小工具
查看>>
excel进行矩阵计算
查看>>
基于Android平台的动态生成控件和动态改变控件位置的方法
查看>>
Java集合(二) Map 架构
查看>>
linux 死机分析
查看>>
BOM
查看>>