[仿南航app開發日記6]自定義背景透明進度條

前言

這篇博客是接着前面的那一篇 的:

[仿南航app開發日記5]查成績界面開發完成以及使用PopupWindow踩過的坑

效果

這裏寫圖片描述

源碼與原理

既然是自定義透明對話框,那麼我直接選擇繼承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是什麼,我前面一篇博客有講

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章