<kbd id="9plqc"><label id="9plqc"></label></kbd>

        <th id="9plqc"></th>
        1. <center id="9plqc"><video id="9plqc"></video></center>
          <sub id="9plqc"><form id="9plqc"><pre id="9plqc"></pre></form></sub>
          <nav id="9plqc"><form id="9plqc"><legend id="9plqc"></legend></form></nav>
          Android 自定義波浪動畫 您所在的位置:網(wǎng)站首頁 隨便給別人算卦 Android 自定義波浪動畫

          Android 自定義波浪動畫

          2024-01-05 03:24| 來源: 網(wǎng)絡(luò)整理| 查看: 265

          waveview

          《Android 自定義波浪動畫之"讓進(jìn)度浪起來~"》轉(zhuǎn)載請注明來自?傻小孩b_移動開發(fā)(http://www.jianshu.com/users/d388bcf9c4d3)喜歡的可以關(guān)注我,不定期總結(jié)文章!您的支持是我的動力哈!

          前言

          首先貝塞爾曲線原理我在這里就不多說了,今天的重點(diǎn)還是講下怎么實(shí)現(xiàn)波浪進(jìn)度的實(shí)現(xiàn)原理,所以想要了解下貝塞爾曲線的程序yuan,請自己百度或者谷歌下哈,多謝合作~如果開發(fā)有什么問題也可以直接加入我的QQ群,詳情請看我的個(gè)人簡介。

          演示

          waveview.gif

          WaveView 實(shí)現(xiàn) (一)如何確定初始化的位置? 首先

          在實(shí)現(xiàn)一個(gè)自定義View的時(shí)候,我們先來觀察下想要的動畫效果分為幾個(gè)層次,如圖所示:

          1、向右的貝塞爾曲線,這里用“normal wave”來表示。? 作用:一直勻速向左的波浪曲線,作為波浪的前景

          2、向右的貝塞爾曲線,這里用“rolling wave”來表示。? 作用:為了是波浪效果更佳逼真,所以添加了一個(gè)向右勻速的波浪曲線,并且滾動速度是“normal wave”的一半

          3、波浪上升高度,這里用“wave height”來表示。? 作用:高度代表進(jìn)度,可以根據(jù)設(shè)置的當(dāng)前進(jìn)度progress與最大進(jìn)度max動態(tài)變化

          其次

          在這里我們先要來說下貝塞爾曲線應(yīng)該怎么畫。剛開始,有可能有程序yuan想過,畫一個(gè)無限長(例如 Integer.MAX_VALUE),足夠大了、固定周期的賽貝爾曲線,然后開啟動畫讓他固定一個(gè)方向移動即可。的確,這種實(shí)現(xiàn)方式是可以的,但是感覺資源特別浪費(fèi),有可能還會出現(xiàn)內(nèi)存溢出、響應(yīng)異常等。所以答案:不建議!

          當(dāng)然,上面那個(gè)思路,我是有著手嘗試過啦。最后還是擇優(yōu)選擇了另一個(gè)思路,畫出兩個(gè)周期的貝塞爾曲線,當(dāng)?shù)谝粋€(gè)貝塞爾曲線滑動到最后一個(gè)Point、接近第二個(gè)貝塞爾曲線的開始Point的時(shí)候,直接讓他復(fù)位,恢復(fù)到最初時(shí)候的狀態(tài),這種繪畫效果還是看起來比無限長的貝塞爾曲線效果沒區(qū)別的。所以,每一次,我們需要計(jì)算4n +1個(gè)Point點(diǎn),為什么要4n+1個(gè)點(diǎn)?下面圖片說明:

          Wave_1.png

          最后

          就是整個(gè)閉合區(qū)間的填充,如圖所示:

          wave_2.png

          我們看下動畫里面,初始化Point的關(guān)鍵代碼:

          /** * Initialize the original wave arts collection point , including normal wave ,rolling wave */ private void initPoint(){ if (isInitPoint){ isInitPoint = false; pointList.clear(); shadpointList.clear(); WAVE_WIDTH = (float) (VIEW_WIDTH / 2.5);//這里開發(fā) 我直接設(shè)置波浪寬度為整個(gè)View的四分之一寬度 WAVE_HEIGHT = VIEW_HEIGHT/getWaveHeight();//波浪高度根據(jù)速度改變 dy = VIEW_HEIGHT;//Started from the bottom, when the height is rise, dy gradually reduce //How many points calculated maximum support int n = Math.round(VIEW_WIDTH / WAVE_WIDTH); //start point for normal wave int startX = 0; Log.i(TAG,"begin point ("+DensityUtil.px2dip(mContext,startX)+" , "+DensityUtil.px2dip(mContext,dy)+")"); for (int i = 0; i < 4*n+1; i++) { .... pointList.add(point); } // start point for rolling wave startX = (int) VIEW_WIDTH; for (int i = 0; i < 4*n+1; i++) { .... shadpointList.add(point); } } }

          從上面的代碼,我們可以觀察到“normal wave”和“rolling wave”初始化Point各自存儲在一個(gè)list上面,并且先根據(jù)波浪的寬度與整個(gè)View的寬度,計(jì)算出最多支持多少個(gè)初始化點(diǎn)(非控制點(diǎn),一個(gè)周期最多三個(gè)Point) int n = Math.round(VIEW_WIDTH / WAVE_WIDTH); 因此便能計(jì)算出4n+1個(gè)point的初始化位置。

          (二)如何浪起來?

          我們直接定位在移動的動畫方法flowingAnimation,根據(jù)代碼,我們可以了解到使用了屬性動畫。

          private void flowingAnimation(){ ObjectAnimator animator = ObjectAnimator.ofFloat(this,"wave",0,100) .setDuration(100); animator.setRepeatCount(INFINITE); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { dx = dx + speed; shd_dx = shd_dx + speed/2;//Half the speed of the normal waves .... rerefreshPoints();//更新初始化點(diǎn) postInvalidate(); } }) ; animator.start(); }

          從代碼可以觀察到,是屬于一個(gè)無限循環(huán)的動畫( animator.setRepeatCount(INFINITE);),并且動態(tài)變化的是dx與shd_dx。因此可以直接觀察在繪制onDraw里面,這兩個(gè)動態(tài)變化的變量起了什么作用,以下截取部分onDraw的代碼:

          for (int i = 0; i < pointList.size(); i++) { int j = i + 1; if (pointList.size() > i) { float start1 = pointList.get(i).x; wavePath.moveTo(start1, dy);//+dy if (j % 2 == 0 && j >= 2) { ... } else { .... }} } .... for (int i = 0; i < shadpointList.size(); i++) { int j = i + 1; if (shadpointList.size() > i) { float start1 = shadpointList.get(i).x + shd_dx; shadPath.moveTo(start1, dy);//+dy if (j % 2 == 0 && j >= 2) { .... } else { .... } } }

          應(yīng)該很明顯可以觀察到,dx是改變“normal wave”周期的起點(diǎn),shd_dx是改變“rolling wave”周期起點(diǎn),因此間接使貝塞爾曲線雙向”浪起來“,有了波浪的效果。

          (三)如何浮起來?

          直接進(jìn)入動畫,觀察動態(tài)變化的變量

          private void riseAnimation(){ .... if (dy > 0) { ... ValueAnimator animator = ValueAnimator.ofFloat(0, s) .setDuration(500); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { ... dy = s; Log.i("yuan", "move m " + m + "dy " + dy); } }); animator.start(); beforDy = sum_dy - sum_dy * progressRatio;//save the last time the higher level } }

          從代碼可以觀察到,動態(tài)變化的是dy,因此波浪浮動的高度由dy所決定,這里難點(diǎn)是這么計(jì)算出當(dāng)我們設(shè)置max和progress的時(shí)候,動態(tài)去變化dy,這里我用一張圖來解釋下:

          (四)回調(diào)監(jiān)聽

          感覺回調(diào)監(jiān)聽感覺沒有好說的~

          首先WaveView是在onDraw進(jìn)行回調(diào)的,但是這里來有個(gè)小問題,如果我們頻繁的繪制,不處理的話每一次都會進(jìn)行回調(diào),這樣也會造成不必要的浪費(fèi)。因此這里,簡單記錄上次的進(jìn)度,通過對比,不同才回調(diào)。

          (五)總結(jié)

          二十幾天沒總結(jié),這期間搞了點(diǎn)東西,也經(jīng)歷了一個(gè)放松的國慶~當(dāng)然,同志們也不能將開發(fā)落下~最后還是:我們也不能只是搬運(yùn)代碼的“程序猿”,更重要我們是需要寫出更高質(zhì)量的代碼,創(chuàng)造的“程序猿”。下面附上源碼,如果喜歡的話給個(gè)star哈~謝謝:

          WaveView 讓進(jìn)度浪起來~

          使用方法,可以直接上github看README

          傻小孩b mark共勉,寫給在成長路上奮斗的你

          喜歡就為我點(diǎn)下喜歡、給我個(gè)github的star吧~ 感謝各位讀者閱讀。



          【本文地址】

          公司簡介

          聯(lián)系我們

          今日新聞

          推薦新聞

          專題文章
            CopyRight 2018-2019 實(shí)驗(yàn)室設(shè)備網(wǎng) 版權(quán)所有
            黄色免费网站在线看,韩国精品在线观看,韩国美女一区二区,99国产热 于都县| 廉江市| 额尔古纳市| 桐梓县| 霞浦县| 大安市| 青神县| 清徐县| 阳朔县| 靖边县| 昌图县| 堆龙德庆县| 泌阳县| 德阳市| 西和县| 昌平区| 东城区| 铜山县| 鸡西市| 如皋市| 通州区| 盐亭县| 永泰县| 山西省| 蒲江县| 岳西县| 甘肃省| 萍乡市| 九龙县| 道真| 资兴市| 迁安市| 桦南县| 长丰县| 堆龙德庆县| 伊金霍洛旗| 洛川县| 和龙市| 曲靖市| 浮山县| 延津县| http://444 http://444 http://444 http://444 http://444 http://444