編輯:關於Android編程
最近,看了好多的APP的等待對話框,發現自己的太lower,於是就研究了一番,最後經過苦心努力,實現一個。
描述就提供這些,一下是代碼的展示,非常的詳細。
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);
}
}
效果圖;

以上就是本文的全部內容,希望對大家的學習有所幫助。
Android學習筆記之應用單元測試實例分析
本文實例講述了Android學習筆記之應用單元測試。分享給大家供大家參考,具體如下:第一步:在AndroidManifest.xml中加入如下兩段代碼:<manif
Android實現帶箭頭的自定義Progressbar
一、閒話: Android原生的進度條可以根據不同的主題有不同的視覺效果,但任何一種主題下的進度條和應用程序的視覺配合起來都顯得格格不入,所以多數時候我們需要自定義Pro
Mono for Android 實現高效的導航(Effective Navigation)
Android 4.0 系統定義了一系列的高效導航方式 (Effective Navigation), 主要包括標簽、下拉列表、以及向上和返回等, 本文介紹如何用 Mon
小米miui8下載 miui8系統全系列機型下載地址大全
MIUI 8是2016年5月10日小米科技發布的全新MIUI 8手機操作系統。小米公司官方此次推出的全新MIUI8系統,在各個方面都進行了大深度的優化。米迷