仿騰訊WiFi網絡檢測動畫

最近做項目要求做一個類似騰訊WiFi網絡檢測的動畫,最近正好項目開發完成,手頭也沒什么事,就給大家分享一下。當時項目也非常緊為了趕周期就沒考慮代碼優化的問題,希望大拿們不喜勿噴。
話不多說先來看看效果(轉成GIF后比較卡頓)

第一步:在沒有旋轉動畫之前呢是一個圖片,把圖片和自定義的旋轉動畫放在一個Layout當中,當開始檢測的時候就打開自定義試圖的動畫。

布局文件

           <RelativeLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <com.zhizun.zhizunwifi.widget.CircleViewPhy
                    android:id="@+id/circle_safe"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_centerInParent="true"
                    app:circleWidth="2dp"
                    app:firstColor="@color/white"
                    app:speed="2"
                    android:visibility="gone"
                    />

                <ImageView
                    android:id="@+id/speed_rotating"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/img_scanning"
                    android:layout_gravity="center_vertical"
                    android:visibility="gone"
                    />

                <ImageView
                    android:id="@+id/speed_icon_safe"
                    android:layout_width="90dp"
                    android:layout_height="90dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/icon_safe"
                    android:layout_gravity="center_vertical"
                    />

            </RelativeLayout>

speed_icon_safe這個就是一張圖片,speed_rotating中間旋轉漸變的扇形圖片,circle_safe從開始畫圓點然后圓弧旋轉一直到檢測完畢畫實心圓弧都有這個自定義試圖完成。

第二步:關鍵的自定義試圖代碼

public class CircleViewPhy extends View {
    /**
     * 第一種顏色
     */
    private int mFirstColor;
    /**
     * 第二種顏色
     */
    private int mSecondColor;
    /**
     * 圓弧的寬度
     */
    private int mCircleWidth;
    /**
     * 畫筆
     */
    private Paint mPaint;

    private Paint wPaint;

    private Paint TPaint;
    /**
     * 圓弧的度數
     */
    private int mProgress;

    /**
     * 圓弧的度數
     */
    private int TProgress;
    /**
     * 圓弧繪制的速度
     */
    private int mSpeed;
    /**
     * 是不是開始繪制下一個圓弧
     */
    private boolean isNext = false;

    private int phase;

    private Rect mSrcRect, mDestRect;


    private float mStartAngle;
    private float mSweepAngle = 0;
    private static final int MIN_ANGLE_SWEEP = 3;
    private static final int MAX_ANGLE_SWEEP = 155;
    private int mAngleIncrement = 3;
    Bitmap bmp;
    private ImageView imageCircle;
    private Context mContext;
    private boolean isFinsh = false;
    private boolean autoRun = false;

    public CircleViewPhy(Context context) {
        this(context, null);
    }

    public CircleViewPhy(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public void setImageCircle(ImageView imageCircle) {
       this.imageCircle = imageCircle;

    }

    public void setfinsh(boolean finsh){
      this.isFinsh = finsh;
    }

    public void setautoRun(boolean run){
        this.autoRun = run;
    }


    /**
     * 獲取自定義控件的一些值
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public CircleViewPhy(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleViewPhy, defStyleAttr, 0);

        mContext = context;

        for (int i = 0; i < a.getIndexCount(); i++) {

            switch (a.getIndex(i)) {
                case R.styleable.CircleViewPhy_firstColor:
                    mFirstColor = a.getColor(a.getIndex(i), Color.WHITE);
                    break;
                case R.styleable.CircleViewPhy_secondColor:
                    mSecondColor = a.getColor(a.getIndex(i), Color.RED);
                    break;
                case R.styleable.CircleViewPhy_speed:
                    mSpeed = a.getInt(a.getIndex(i), 20);
                    break;
                case R.styleable.CircleViewPhy_circleWidth:
                    mCircleWidth = a.getDimensionPixelOffset(a.getIndex(i), (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
                    break;
            }
        }
        a.recycle();
        mPaint = new Paint();
        wPaint = new Paint();
        TPaint = new Paint();


            //繪圖線程
            new Thread() {
                @Override
                public void run() {
                    while (true) {
                        if (autoRun){
                            if (isFinsh){
                                TProgress ++;
                                if (TProgress == 360){
                                    TProgress = 360;
                                }
                            }

                            if (mProgress != 360) {
                                mProgress++;
                            }else {

                                final float angle = 5;
                                mStartAngle += angle;

                                if (mStartAngle > 360) {
                                    mStartAngle -= 360;
                                }



                                if (mSweepAngle > MAX_ANGLE_SWEEP) {
                                    mAngleIncrement = -mAngleIncrement;
                                } else if (mSweepAngle < MIN_ANGLE_SWEEP) {
                                    mSweepAngle = MIN_ANGLE_SWEEP;
                                } else if (mSweepAngle == MIN_ANGLE_SWEEP) {
                                    mAngleIncrement = -mAngleIncrement;
                                }

                                mSweepAngle += mAngleIncrement;
                            }

                        }
                        postInvalidate();
                        try {
                            if (mProgress == 360 && !isFinsh){

                                Thread.sleep(mSpeed + 5); //通過傳遞過來的速度參數來決定線程休眠的時間從而達到繪制速度的快慢
                            }else {

                                Thread.sleep(mSpeed); //通過傳遞過來的速度參數來決定線程休眠的時間從而達到繪制速度的快慢
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        int center = getWidth() / 2;
        int radius = center - mCircleWidth / 2;
        
        mPaint.setStrokeWidth(mCircleWidth); // 設置圓環的寬度
        wPaint.setStrokeWidth(mCircleWidth);
        TPaint.setStrokeWidth(mCircleWidth + 8);

        mPaint.setAntiAlias(true); // 消除鋸齒
        wPaint.setAntiAlias(true); // 消除鋸齒
        TPaint.setAntiAlias(true);

        mPaint.setStyle(Paint.Style.STROKE); // 設置空心
        wPaint.setStyle(Paint.Style.STROKE);
        TPaint.setStyle(Paint.Style.STROKE);

        RectF oval = new RectF(center - radius + 5, center - radius + 5, center + radius - 5, center + radius - 5); // 用于定義的圓弧的形狀和大小的界限
        RectF oval0 = new RectF(center - radius + 50, center - radius + 50, center + radius - 50, center + radius - 50); // 用于定義的圓弧的形狀和大小的界限




        if (!isFinsh){
            Path path = new Path();
            path.addCircle(0, 0, 5, Path.Direction.CCW);
            PathEffect pathEffect = new PathDashPathEffect(path,30, phase, PathDashPathEffect.Style.ROTATE);
            mPaint.setPathEffect(pathEffect);
            mPaint.setColor(mFirstColor); // 設置圓環的顏色
            canvas.drawArc(oval, -90, mProgress, false, mPaint); // 根據進度畫圓弧

            if (mProgress == 360){
                wPaint.setColor(getResources().getColor(R.color.white_alpha_144)); // 設置圓環的顏色
                canvas.drawArc(oval0, -90, 360, false, wPaint);

                TPaint.setColor(Color.WHITE);
                canvas.drawArc(oval, mStartAngle, mSweepAngle, false, TPaint);

            }
        }else {
            wPaint.setColor(getResources().getColor(R.color.white)); // 設置圓環的顏色
            canvas.drawArc(oval0, -90, TProgress, false, wPaint);
        }


        }



}

當時本來說是圓環要顏色變化的,但是后來統一改成白色了,所以代碼中顏色的片段就不用管了。我先來說說思路,首先動畫開始是一個圓點的畫圓弧動畫。
把筆觸設置為圓點

            Path path = new Path();
            path.addCircle(0, 0, 5, Path.Direction.CCW);
            PathEffect pathEffect = new PathDashPathEffect(path,30, phase, PathDashPathEffect.Style.ROTATE);
            mPaint.setPathEffect(pathEffect);

所有的動畫效果都是通過畫筆在畫圖的過程中設置一個線程休眠來體現的。

                postInvalidate();
                        try {
                            if (mProgress == 360 && !isFinsh){

                                Thread.sleep(mSpeed + 5); //通過傳遞過來的速度參數來決定線程休眠的時間從而達到繪制速度的快慢
                            }else {

                                Thread.sleep(mSpeed); //通過傳遞過來的速度參數來決定線程休眠的時間從而達到繪制速度的快慢
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

當圓點的圓弧畫到360度之后就開始畫第二層的實心圓

           if (mProgress == 360){
                wPaint.setColor(getResources().getColor(R.color.white_alpha_144)); // 設置圓環的顏色
                canvas.drawArc(oval0, -90, 360, false, wPaint);

                TPaint.setColor(Color.WHITE);
                canvas.drawArc(oval, mStartAngle, mSweepAngle, false, TPaint);

            }
<declare-styleable name="CircleViewPhy">
        <attr name="firstColor" format="color"/>
        <attr name="secondColor" format="color"/>
        <attr name="circleWidth" format="dimension"/>
        <attr name="speed" format="integer"/>
    </declare-styleable>

當檢測過程完畢之后又Activity傳入isFinsh為True標識完畢,停止繪制動畫,畫最后一層高亮的圓弧。

大概就是這樣了,大家可以根據這個代碼自己改成想要的動畫效果!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,737評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,173評論 4 61
  • http://pan.baidu.com/s/1jI3MS8Q Teableau練習用的,一個超市的銷售,利潤,日...
    老王叔叔閱讀 984評論 0 0
  • 一.河畔 我家邊的河是漢江,這條河一般認為是發源于秦嶺,上游有一個著名的丹江口水庫,在武漢市注入長江,是干流長江最...
    追夕陽的人閱讀 589評論 9 4
  • 故事是在我環繞世界一圈以后,回到故鄉,在高中時代就讀學校的實驗樓頂,俯瞰四周準備跳樓時發生的。 傍晚剛剛下過了陣雨...
    超智少年李魷魚閱讀 924評論 0 1