Android自訂等待對話方塊_Android

來源:互聯網
上載者:User

最近,看了好多的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);   }  } 

效果圖;

以上就是本文的全部內容,希望對大家的學習有所協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.