前言
這篇博客是接着前面的那一篇 的:
效果
源碼與原理
既然是自定義透明對話框,那麼我直接選擇繼承Dialog,然後創建對話框,先看源碼:
package cn.karent.nanhang.UI;
import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import cn.karent.nanhang.R;
/**
* Created by wan on 2016/12/27.
* 進度對話框
*/
public class ProgressDialog extends Dialog {
private ProgressDialog(Context context) {
super(context);
}
private ProgressDialog(Context context, int theme) {
super(context, theme);
}
public static class Builder {
private Context mContext;
public Builder(Context context) {
mContext = context;
}
public ProgressDialog create() {
ProgressDialog p = new ProgressDialog(mContext, R.style.LoginDialogTheme);
View v = LayoutInflater.from(mContext).inflate(R.layout.load_dialog_layout, null);
p.addContentView(v, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
Window window = p.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = 700;
lp.height = 700;
window.setAttributes(lp);
return p;
}
}
}
上面有定義高度和寬度,當然還設置了一個主題:
ProgressDialog p = new ProgressDialog(mContext, R.style.LoginDialogTheme);
至於這個主題,我在前面一篇創建登陸對話框時就使用過,我還是將sttyle放上來吧:
<style name="LoginDialogTheme" parent="Theme.AppCompat.DayNight.Dialog">
<item name="android:windowTitleStyle">@null</item>
<item name="android:windowBackground">@null</item>
</style>
這個style的功能就是去除了背景和標題,當然了,上面是繼承Dialog,但是必須要自己寫佈局啊,佈局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<cn.karent.nanhang.UI.ProgressView
android:id="@+id/load_dialog_progressView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginTop="10dp"
android:text="正在加載中。。。"
android:textColor="#dfdbdb"/>
</LinearLayout>
</RelativeLayout>
依然是比較普通的佈局文件,其中使用了一個自定義類,那就是
cn.karent.nanhang.UI.ProgressView
這個就是自定義進度條的核心了,我們看下源碼:
package cn.karent.nanhang.UI;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PorterDuff;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.View;
import cn.karent.nanhang.R;
/**
* Created by wan on 2016/12/27.
* 重複繪製小圓點
*/
public class ProgressView extends View {
/**
* 全局上下文
*/
private Context mContext;
/**
* 圖像變換矩陣
*/
private Matrix mMatrix = new Matrix();
/**
* 要繪製的背景圖,也就是那個旋轉的點點
*/
private Bitmap mBitmap;
/**
* 圖片的寬度
*/
private int mWidth;
/**
* 圖片的寬度
*/
private int mHeight;
public ProgressView(Context context) {
super(context);
}
public ProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
//從資源加載bitmap對象
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.pic_dlg_loading);
mWidth = mBitmap.getWidth();
mHeight = mBitmap.getHeight();
//執行循環
new LoopAnimation().execute();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mMatrix.preRotate(6, mWidth / 2, mHeight / 2);
canvas.drawBitmap(mBitmap, mMatrix, null);
}
/**
* 循環動畫,不停的觸發旋轉動畫
*/
class LoopAnimation extends AsyncTask<Void, Void, Void> {
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
invalidate();
}
@Override
protected Void doInBackground(Void... params) {
int rotate = 0;
while( true ) {
try {
Thread.sleep(100);
} catch(InterruptedException e) {
e.printStackTrace();
}
publishProgress();
}
}
}
}
看到了沒,原理就是開個線程,然後不斷的繪製一張圖片,這裏面有幾點需要注意的地方:
mMatrix.preRotate(6, mWidth / 2, mHeight / 2);
這個是旋轉的代碼,必須知道圖片的中心 (後面那兩個參數),否則將會以原點爲中心旋轉,得到的結果絕對不是你想要的,另外還有一點需要注意,因爲我們前面將對話框的背景去掉,所以默認不會清楚畫布上面的內容,畫出來的圖形是不斷疊加,在普通的java繪圖當中我們的做法是在繪製任何東西之前先繪製一個白色背景,但是這裏我們要繪製一個透明的背景:
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
這樣就會清除原先繪製的背景 從而重新繪製了,好了,要點就是這麼多。
我現在的測試的是直接在Activity的onCreate方法裏面創建對話框,真正使用的時候可以先創建,然後在訪問網絡完成將對話框dismiss掉,代碼如下:
new ProgressDialog.Builder(this).create().show();
上面的加載的是再ScoreActivity的onCreate方法裏面,至於ScoreActivity是什麼,我前面一篇博客有講