Android 自定義view之復雜動畫(path,canvas坐昙,paint...)

前言

為什么起了這么個標題呢绳匀,因為我們接下來要做的動畫運用到了多個知識點,如果自己實操幾遍,基本android中繪圖方面的知識點就掌握的差不多了

先看下動畫圖

首先讓我們來看一下動畫效果 ,原文地址

有教程了為什么還要專門再寫一篇疾棵?因為小編腦子比較笨戈钢,理解不了原文寫的啥意思,就寫了另一種實現(xiàn)方法是尔,本文通俗易懂殉了,不懂留言即可

分析動畫

  • 1、加載過程拟枚,畫藍色圓環(huán)薪铜,當進度為100%時,圓環(huán)完成
  • 2恩溅、從右側拋出藍色小方塊隔箍,小方塊沿著曲線到達圓環(huán)正上方
  • 3、藍色小方塊下落脚乡,下落過程中蜒滩,逐漸變長,當方塊與圓圈接觸時奶稠,進入圓環(huán)的部分變粗帮掉,同時圓環(huán)逐漸被擠壓,變成橢圓形
  • 4窒典、方塊底端到達圓環(huán)中心后蟆炊,發(fā)出三個分叉向圓周延伸,同時橢圓被撐大瀑志,逐漸恢復回圓形
  • 5涩搓、圓環(huán)變綠色,畫出綠色勾√

仔細分析一下第一部分劈猪,則是canvas.drawArc就可以昧甘,隨著進度改變初始位置,和弧長
第二部分也不難沒和第一部分基本一樣战得,只不過圓變大了
第三部分算是最難的部分了充边,先路徑,判斷

第一部分常侦、隨進度增加圓弧增加浇冰,最后成圓

上面我們分析也提到,實現(xiàn)并不難聋亡,這里我們用handle的定時原理來代替進度

MainActivity

    public void button(View view){
        switch (view.getId()){
            case R.id.btn2:
                //定時器原理
                final Handler handler=new Handler();
                i=0;
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (i<360){
                        i+=10;
                        mMyView.setProgress(i);
                        handler.postDelayed(this,100);
                      }else {
                            mMyView.finishSuccess();
                        }
                    }
                },1000);
        }
    }

然后在我們的自定義MyView中肘习,設置setProgress參數(shù),收到進度值,刷新頁面坡倔,onDrow更新進度值漂佩,繪制圓弧隨進度改變


    /**
     * 開始完成動畫
     */
    private void start(){
        post(new Runnable() {
            @Override
            public void run() {
                mRotateAnimation.start();
            }
        });
    }

    public void setProgress(int progress) {
        status = 0;
        this.progress = progress;
        postInvalidate();
    }

    /**
     * loading成功后調用
     */
    public void finishSuccess() {
        setProgress(maxProgress);
        this.isSuccess = true;
        status = 1;
        start();
    }

    /**
     * loading失敗后調用
     */
    public void finishFail() {
        setProgress(maxProgress);
        this.isSuccess = false;
        status = 1;
        start();
    }
}

重寫onSizeChanged

protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mWidth = w;
        mHeight = h;

        //居中設置 圓的半徑  小編這里的半徑為130
        radius = Math.min(getMeasuredWidth(),getMeasuredHeight())/4-strokeWidth;

        //居中繪圓  小編這里的圓為150脖含,150,410投蝉,410
        mRectF.set(new RectF(radius+strokeWidth, radius+strokeWidth, 3 * radius+strokeWidth, 3 * radius+strokeWidth));
}

重寫onDraw

圓弧起始狀態(tài)

圓弧最終狀態(tài)

可以看到养葵,首先圓弧有一定的起始角度,我們知道瘩缆,在Android坐標系中港柜,0度其實是指水平向右開始的 也就是起點的起始角度,其實是-90度咳榜,終點的起始角度,其實-150度

而整個過程中爽锥, 起點:-90度涌韩,逆時針旋轉270度,最后回到0度位置 終點:-150度氯夷,與起點相差60度臣樱,最后相差360度,與起點重合

所以當progress=1腮考,也就是動畫完成時雇毫,起點會減去270度,那么對應每個progress 起點的位置應該是

-90-270*progress

當progress=1,終點和起點相差360度踩蔚,而一開始就相差60度,所以整個過程就是多相差了300度棚放,那么對應每個progress,終點和起點應該相差

-(60+precent*300)

根據(jù)上面的結論馅闽,我們得到圓弧的具體繪制方式如下:

@Override
    protected void onDraw(Canvas canvas) {
        switch (status){
            case 0:
                //設置一下maxProgress最大為360(private int maxProgress=360飘蚯;),這里設置多少無所謂福也,設置360局骤,方便理解
                float precent = 1.0f*progress/maxProgress;
                canvas.drawArc(mRectF, startAngle-270*precent, -(60 + precent*300), false, circlePaint);
                break;

當然我們要在初始化的時候定義一下paint

circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.argb(255, 48, 63, 159));
circlePaint.setStrokeWidth(strokeWidth);
circlePaint.setStyle(Paint.Style.STROKE);

第一部分完成,看一下效果圖

圓弧運動狀態(tài)

第二部分暴凑、拋出小方塊

首先構思如何繪出小方塊峦甩,其實方法有多種,可以用canvas的drawLine现喳,也可以drawArc凯傲,小編這里用的是drawArc,有開始角度嗦篱,和橫掃角度泣洞,這樣會很方便的控制移動,而用drawLine會很麻煩默色,原文用的drawLine球凰,反正我是沒有看懂狮腿,如果你看懂了,可以留言教教我

先看一張小編用軟件繪制的圖呕诉,我們可以看出深藍色的圓為小圓缘厢,紅色的為大圓(沒畫完整),那么大圓的弧度右上部分就是小方塊的運動軌跡

第一種方法

1.假設運動軌跡是某個圓的一段弧甩挫,那么根據(jù)勾股定理有如下方程

(X+R)^2 + (2R)^2 = (X+2R)^2

2.解得X=R/2(其實也很容易解贴硫,就是勾三股四玄五) ,小編這里的R為130(上面有寫到),我們只需要知道圓心角是多少度伊者,就可以設置運動軌跡了

弦長為(R)^2 + (2R)^2 =L^2,解L=根5 * R

3.已知弦長L和半徑R求大圓半徑:

sinA=(1/2)*L/R=L/(2R),圓心角=2asin(L/(2R))
圓心角*180/π=度數(shù)   即2asin(L/(2R))*180/π=度數(shù)

Android中這樣表示

(2*Math.asin(290.68/650))*180/Math.PI

第二種方法

這也是最好用的方法英遭,反正原文作者的那種我是看不懂

如果勾股定理你已經(jīng)忘得一干二凈了,那么你也可以直接運用Android的度數(shù)公式

那么如何計算任意兩點間直線的傾斜角呢?只需要將兩點x,y坐標分別相減得到一個新的點(x2-x1,y2-y1)亦渗。然后利用它求出角度即可——Math.atan2(y2-y1,x2-x1)挖诸。

Math.atan2(y2-y1,x2-x1) * 180.0 / Math.PI

        //拋出動畫
        System.out.println(endAngle);
        mRotateAnimation = ValueAnimator.ofFloat(0f, (float)(Math.atan2(-260, 195) * 180.0 / Math.PI));
        mRotateAnimation.setDuration(1000);
        mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        mRotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                curSweepAngle = (float) animation.getAnimatedValue();
                invalidate();
            }
        });

      //設置監(jiān)聽
        mRotateAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                curSweepAngle = 0;
                if (isSuccess) {
                    status = 2;
                    mDownAnimation.start();
                } else {
                    status = 5;
                    mCommaAnimation.start();
                }
            }
        });

我們的小方塊就這樣完成了

方塊下落,壓縮圓環(huán)

可以說下落過程法精,是整個動畫中最復雜的過程了多律,包括方塊下落,圓環(huán)擠壓搂蜓,方塊變粗三個過程狼荞,整個過程,從方塊下落開始帮碰,到方塊底部到底圓心

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末相味,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子殉挽,更是在濱河造成了極大的恐慌攻走,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件此再,死亡現(xiàn)場離奇詭異昔搂,居然都是意外死亡,警方通過查閱死者的電腦和手機输拇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門摘符,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人策吠,你說我怎么就攤上這事逛裤。” “怎么了猴抹?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵带族,是天一觀的道長。 經(jīng)常有香客問我蟀给,道長蝙砌,這世上最難降的妖魔是什么阳堕? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮择克,結果婚禮上恬总,老公的妹妹穿的比我還像新娘。我一直安慰自己肚邢,他們只是感情好壹堰,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骡湖,像睡著了一般贱纠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上响蕴,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天谆焊,我揣著相機與錄音,去河邊找鬼换途。 笑死,一個胖子當著我的面吹牛刽射,可吹牛的內容都是我干的军拟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼誓禁,長吁一口氣:“原來是場噩夢啊……” “哼懈息!你這毒婦竟也來了?” 一聲冷哼從身側響起摹恰,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辫继,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后俗慈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姑宽,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年闺阱,在試婚紗的時候發(fā)現(xiàn)自己被綠了炮车。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡酣溃,死狀恐怖瘦穆,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情赊豌,我是刑警寧澤扛或,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站碘饼,受9級特大地震影響熙兔,放射性物質發(fā)生泄漏悲伶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一黔姜、第九天 我趴在偏房一處隱蔽的房頂上張望拢切。 院中可真熱鬧,春花似錦秆吵、人聲如沸淮椰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽主穗。三九已至,卻和暖如春毙芜,著一層夾襖步出監(jiān)牢的瞬間忽媒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工腋粥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留晦雨,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓隘冲,卻偏偏與公主長得像闹瞧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子展辞,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內容