首页 > 系统 > Android > 正文

Android自定义等待对话框

2020-01-02 07:02:21
字体:
来源:转载
供稿:网友

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

  • 自定义一个LoadingIndicatorView(extends View )类
  • 编写values/attrs.xml,在其中编写styleable和item等标签元素
  • 在布局文件中LoadingIndicatorView使用自定义的属性(注意namespace)
  • 在LoadingIndicatorView的构造方法中通过TypedArray获取

描述就提供这些,一下是代码的展示,非常的详细。
1、自定义属性的声明文件

<declare-styleable name="AVLoadingIndicatorView">     <attr name="indicator">       <flag name="BallSpinFadeLoader" value="22"/>     </attr>     <attr name="indicator_color" format="color"/>   </declare-styleable> <pre name="code" class="html">

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();     }   }  } 

对话框的布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  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" >  <LinearLayout    android:layout_width="wrap_content"    android:layout_weight="1"    android:gravity="center"    android:layout_height="wrap_content">    <com.chni.lidong.androidtestdemo.loading.AVLoadingIndicatorView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      app:indicator="BallSpinFadeLoader"      app:indicator_color="@color/green"      />  </LinearLayout>  <TextView    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" /></LinearLayout>

对话框的样式:

<!-- 自定义Loading Dialog --><style name="loading_dialog_style" parent="@android:style/Theme.Dialog">  <item name="android:windowFrame">@null</item>  <item name="android:windowNoTitle">true</item>  <item name="android:windowBackground">@color/transparent</item>  <item name="android:windowIsFloating">true</item>  <item name="android:windowContentOverlay">@null</item></style>

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);   }  } 

效果图;

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表