Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義View——仿vivo i管家病毒掃描動畫效果

Android自定義View——仿vivo i管家病毒掃描動畫效果

編輯:關於Android編程

技術是永無止境的,如果真的愛技術,那就勇敢的堅持下去。我很喜歡這句話,當我在遇到問題的時候、當我覺得代碼枯燥的時候,我就會問自己,到底是不是真的熱愛技術,這個時候,我心裡總是起著波瀾,我的答案是肯定的,我深深的愛著這門技術。

今天我們繼續聊聊Android的自定義View系列。先看看效果吧:

這裡寫圖片描述

這個是我手機殺毒軟件的一個動畫效果,類似於雷達搜索,所以用途還是很廣泛的,特別是先了解一下這裡的具體邏輯和寫法,對技術的進步一定很有用。

先簡單的分析一下這裡的元素,主要有四個圓、一個扇形、還有八條虛線。當知道這些以後,代碼就可以開始寫了。

先看看這裡用到了哪些變量。

    private float mWidth;

    private float mHeight;

    private Paint mPaint, mPaint2, mPaint3, mPaint4, mLinePaint;

    private RectF mRectF;

    private float startAngle = 360;

    private float radius1, radius2, radius3, radius4;
    private Path path;

不是很多,有畫筆6個,然後是寬與高,還有就是角度以及四個圓的半徑以及一個矩形、當然還有繪制虛線的Path類。接下來是初始化的操作。

    // 初始化畫筆操作
    private void initData() {
        mPaint = new Paint();
        mPaint.setStrokeWidth(1);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Style.STROKE);
        mPaint.setColor(Color.parseColor("#ffffff"));

        mPaint2 = new Paint();
        mPaint2.setStrokeWidth(5);
        mPaint2.setColor(Color.parseColor("#00ff00"));

        mPaint3 = new Paint();
        mPaint3.setStrokeWidth(3);
        mPaint3.setAntiAlias(true);
        mPaint3.setStyle(Style.STROKE);
        mPaint3.setColor(Color.parseColor("#ffffff"));

        mPaint4 = new Paint();
        mPaint4.setStrokeWidth(2);
        mPaint4.setAntiAlias(true);
        mPaint4.setStyle(Style.STROKE);
        mPaint4.setColor(Color.parseColor("#ffffff"));

        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLinePaint.setStrokeWidth(1);
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setAntiAlias(true);
        mLinePaint.setColor(Color.parseColor("#ffffff"));

        path = new Path();

    }

這裡包括了五個畫筆的初始化操作、一個路徑的初始化操作。注意每個畫筆的具體樣式是不一樣的,這樣方便實現不同的效果。
初始化的操作完了之後,就是給變量賦值了,還是一樣的,我們選擇在onSizeChange()裡面對變量進行賦值。代碼如下:


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = getWidth();
        mHeight = getHeight();
        mRectF = new RectF((float) (mWidth * 0.1), (float) (mWidth * 0.1),
                (float) (mWidth * 0.9), (float) (mWidth * 0.9));
        // 繪制漸變效果
        LinearGradient gradient = new LinearGradient((float) (mWidth * 0.3),
                (float) (mWidth * 0.9), (float) (mWidth * 0.1),
                (float) (mWidth * 0.5), new int[] {
                        Color.parseColor("#458EFD"), Color.GREEN,
                        Color.parseColor("#458EFD"), Color.WHITE,
                        Color.parseColor("#458EFD") }, null,
                Shader.TileMode.CLAMP);
        mPaint2.setShader(gradient);
        // 四個圓的半徑
        radius1 = (float) (mWidth * 0.4);
        radius2 = (float) (mWidth * 0.3);
        radius3 = (float) (mWidth * 0.2);
        radius4 = (float) (mWidth * 0.1);

    }

其實很明顯啊,我們在前面講的幾個自定義的View中,幾乎所有的變量初值都是在這個方法裡面寫的,這個方法究竟有什麼特點呢?其實這個是系統回調方法,是系統調用的,它的方法名已經告訴我們了,這個方法會在這個view的大小發生改變是被系統調用,我們要記住的就是view大小變化,這個方法就被執行就可以了。最主要的是,它還在onDraw方法之前調用。

還記得之前的效果嗎?裡面有一個漸變,這個漸變就是代碼裡LinearGradient 類的操作結果了,具體的用法,我在後面會專門去解釋它。

到了這裡,基本上所有的准備工作都完成了,接下來進行真真的繪圖。
先看看onDraw方法裡面做的操作:


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvasArc(canvas);
        canvasArc2(canvas);
        canvasCircle(canvas);
        canvasLine(canvas);

    }

這裡有畫圓的,有畫扇形的,也有畫線的,所以可以發現,我們所有看到的效果,都是在onDraw方法裡面實現的。我們具體看看每一個方法:

第一個繪制扇形:

    // 繪制旋轉的扇形
    private void canvasArc(Canvas canvas) {
        canvas.drawArc(mRectF, startAngle, 60, true, mPaint2);
    }

只有兩行代碼,也很容易理解,那麼第二個扇形也是差不多:

    // 繪制旋轉的扇形
    private void canvasArc2(Canvas canvas) {
        canvas.drawArc(mRectF, startAngle, 1, true, mPaint3);
    }

值得注意的是,第二個的扇形的角度是1,為什麼是1呢,原來我這裡只是想要它旋轉角度的效果,並不需要它有多寬,所以在具體實現自定義View的時候,也要學會活學活用。

兩個扇形已經畫好了,那就看看四個圓怎麼畫:

    // 繪制四個圓
    private void canvasCircle(Canvas canvas) {
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius1, mPaint3);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius2, mPaint);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius3, mPaint);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius4, mPaint4);
    }

四個圓就是四行代碼,怎麼樣,很簡單吧?

注意他們所用的畫筆是不太一樣的,這裡是比較容易忽視的地方。

最後來看看我糾結很久的畫虛線的操作,這裡真是把我卡了好一會兒,先看看代碼:


    // 繪制虛線
    private void canvasLine(Canvas canvas) {
        int lineCount = 8;
        for (int i = 0; i < lineCount; i++) {
            path.moveTo(mWidth / 2, mHeight / 2);
            path.lineTo(radius1, radius4);
            PathEffect effects = new DashPathEffect(new float[] {
                    (float) (mWidth * 0.005), (float) (mWidth * 0.02),
                    (float) (mWidth * 0.005), (float) (mWidth * 0.02) }, 0);
            mLinePaint.setPathEffect(effects);
            canvas.drawPath(path, mLinePaint);
            canvas.rotate(45, mWidth / 2, mHeight / 2);
        }

    }

按理說,繪制虛線,本質也是畫線,但是我一開始是用canvas.drawLine方法,但是沒有效果,網上查找了資料,才知道可能是版本的問題,於是我換用了path。

到了這個時候,全部效果已經出來了,那麼為了讓她動起來,我們還是要加點邏輯,我的思路是這樣的:

定義一個線程,然後通過改變扇形的開始角度來實現動畫的效果。

代碼如下:

class MyThread extends Thread {

        @Override
        public void run() {

            while (true) {
                if (running) {
                    SystemClock.sleep(200);
                    handler.sendEmptyMessage(2);
                }
            }

        }
    }

    private boolean running = true;

    public Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            synchronized (this) {
                if (startAngle < 1) {
                    startAngle = 360;
                } else {
                    startAngle--;
                    invalidate();
                }
            }
        };

    };

到了這裡,基本可以實現動畫效果了,為了讓控件更好的被外面所用,我們還像外面暴露了一些方法。

    // 開啟動畫
    public void setStartAngle() {
        thread = new MyThread();
        thread.start();

    }

    // 重新開啟動畫
    public void startAnge() {
        running = true;
    }

    // 暫停動畫
    public void stopAnge() {
        running = false;
    }

    // 是否在運動
    public boolean isRunning() {
        return running;
    }

最後看看我在MainActivity.java的操作:

/**
 * 小瓶蓋 2016年7月12日16:35:26
 * 
 * @author 自定義View——仿Vivo i管家病毒掃描動畫效果
 * 
 *         博客地址:http://blog.csdn.net/qq_25193681
 */
public class MainActivity extends ActionBarActivity {
    private VirusKilling mVirusKilling;
    float mVirusKillingValue = 360;
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        mVirusKilling = (VirusKilling) findViewById(R.id.Virus_Killing);

        tv = (TextView) findViewById(R.id.tv);
        // 傳入TextView,改變下方的文字的時候用到
        mVirusKilling.setTextView(tv);
        // 第一次打開的時候就開始更新動畫
        mVirusKilling.setStartAngle();

    }

    /**
     * 點擊事件的處理
     * 
     * @param v
     */
    public void onStop(View v) {
        TextView tv = (TextView) v;
        if (mVirusKilling.isRunning()) {
            tv.setText("繼續掃描");
            mVirusKilling.stopAnge();
        } else {
            tv.setText("停止掃描");
            mVirusKilling.startAnge();
        }

    }

    @Override
    protected void onPause() {
        mVirusKilling.stopAnge();
        super.onPause();

    };

    @Override
    protected void onStart() {
        mVirusKilling.startAnge();
        super.onStart();

    }
}

還有布局文件:







    

     

       






     

     

       

       








一個背景效果的代碼:



    
    




到現在,所有的效果都出來了,可能講的不是很詳細,但是代碼是沒有問題的,代碼也不多,多看幾次也很容易理解。

最後我把源碼貼上來:源碼地址

現在還是開始寫博客,技術可能不是很高端,但是日子還長,期待我們一起進步。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved