Android實(shí)現(xiàn)炫酷的寫(xiě)文字動(dòng)畫(huà)效果

目錄

目錄

效果展示

實(shí)現(xiàn)原理

實(shí)現(xiàn)原理簡(jiǎn)單的講就是先獲取你想要實(shí)現(xiàn)動(dòng)畫(huà)的文字的路徑憔四,然后利用PathMeasure與Animator結(jié)合便可實(shí)現(xiàn)文字寫(xiě)出來(lái)的動(dòng)畫(huà)效果。當(dāng)然這么說(shuō)的話屬實(shí)有些草率秒际,接下來(lái)我就詳細(xì)的講一下控件的實(shí)現(xiàn)原理。

1. 文字路徑的獲取
文字路徑的獲取可以通過(guò)Paint的getTextPath方法來(lái)獲取娄徊,但是這里需要注意的是Paint的Style需要設(shè)置為Paint.Style.STROKE因?yàn)槿绻荘aint.Style.FILL的話會(huì)使文字看起來(lái)很別扭闽颇。

Paint.Style.STROKE

Paint.Style.FILL

2. PathMeasure+Animator實(shí)現(xiàn)動(dòng)畫(huà)
這里需要通過(guò)PathMeasure的構(gòu)造方法或者通過(guò)PathMeasure的setPath方法將獲取的文字路徑賦給PathMeasure這樣才能對(duì)路徑進(jìn)行截取。

PathMeasure(tempPath, false)//通過(guò)構(gòu)造方法
PathMeasure().setPath(tempPath, false)//通過(guò)setPath方法

將文字路徑賦給PathMeasure后我們便可利用Animator實(shí)現(xiàn)文字路徑的動(dòng)畫(huà)了寄锐,這里我使用的是ValueAnimator讓值從0升到1(也可以理解為百分百)。

mAnimation = ValueAnimator.ofFloat(0f, 1f)
...省略部分代碼
mAnimation!!.addUpdateListener {
     mCurrentProcess = it.animatedValue as Float
     invalidate()
}
 mAnimation!!.start()

然后根據(jù)動(dòng)畫(huà)的進(jìn)度結(jié)合PathMeasure不斷的截取出文字路徑的對(duì)應(yīng)長(zhǎng)度并繪制出來(lái)。

mPathMeasure!!.getSegment(0F, mPathMeasure!!.length * mCurrentProcess, mDst, true)//獲取路徑片段(這里的mDst是用來(lái)存儲(chǔ)截取出來(lái)的路徑)
canvas!!.drawPath(mDst, mPaint)//繪制路徑

不過(guò)這里需要注意的是PathMeasure通過(guò)getSegment方法截取路徑只能取到當(dāng)前所在封閉路徑可婶,而如果想要遍歷所有的路徑則需調(diào)用PathMeasure的nextContour方法直到nextContour方法返回的值為false即可,說(shuō)到這里有些同學(xué)可能會(huì)有點(diǎn)迷椎扬,這里畫(huà)圖解釋惫搏。


3. 文字的換行問(wèn)題
由于使用自定義View繪制文字它不會(huì)主動(dòng)的去換行因此只能通過(guò)我們自己計(jì)算來(lái)讓文字換行蚕涤。
這里我們使用Paint的getTextWidths來(lái)獲取所有字符的寬度,然后通過(guò)循環(huán)疊加字符的寬度茴丰,每當(dāng)字符的寬度總和大于控件的寬度時(shí)我們便進(jìn)行換行,這里的換行則是存儲(chǔ)下當(dāng)前遍歷到的字符的索引值贿肩,然后根據(jù)這個(gè)索引值對(duì)整串字符串進(jìn)行截取來(lái)實(shí)現(xiàn)龄寞。

具體代碼如下:

 val textWidths = FloatArray(mText.length + 1)
mPaint.getTextWidths(mText, 0, mText.length, textWidths)
var tempTextWidthSum = 0f
var tempViewWidth = 0//控件的寬度
...省略部分代碼
for (i in 0..(textWidths.size - 1)) {
       tempTextWidthSum += textWidths[i]
       if (tempTextWidthSum >tempViewWidth ) {
       mTextLineCountList.add(i)//存儲(chǔ)字符的索引值
       tempTextWidthSum = textWidths[i]//因?yàn)楫?dāng)前已經(jīng)比控件寬度大了所以在重新計(jì)算的時(shí)候需要將這個(gè)字符的寬度加進(jìn)去(因?yàn)檫@已經(jīng)是第二行了)
       }
}
mTextLineCountList.add(mText.length)//將最后的字符索引加進(jìn)去,不然會(huì)缺字

控件的使用

為了方便使用我加了幾個(gè)自定義屬性:

 <declare-styleable name="PathAnimTextView">
        <!--文字顏色-->
        <attr name="animTextColor" format="color"/>
        <!--文字大小-->
        <attr name="animTextSize" format="float"/>
        <!--文字畫(huà)筆寬度-->
        <attr name="animTextStrokWidth" format="float"/>
        <!--動(dòng)畫(huà)文字-->
        <attr name="animText" format="string"/>
        <!--動(dòng)畫(huà)的速度-->
        <attr name="animSpeed">
            <!--快-->
            <enum name="fast" value="0"/>
            <!--慢-->
            <enum name="slow" value="1"/>
            <!--中速-->
            <enum name="medium" value="2"/>
        </attr>
        <!--字體庫(kù)的名稱-->
        <attr name="animTextTypeFace" format="string"/>
        <!--文字行間距-->
        <attr name="animTextLineMargen" format="float"/>
    </declare-styleable>

布局中的使用:

<com.hehuidai.customview.one.animtextview.PathAnimTextView
        android:id="@+id/patv"
        app:animTextColor="#ff0000"
        app:animTextStrokWidth="2"
        app:animTextSize="80"
        app:animSpeed="fast"
        app:animText="Animation TextView"
        app:animTextTypeFace="Muyao-Softbrush.ttf"http://這里的字體文件需要放到assets文件中
        app:animTextLineMargen="0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

代碼中開(kāi)啟動(dòng)畫(huà):

patv.startTextAnim()

代碼中設(shè)置文字:

patv.setText("Animation TextView")

控件源碼

控件源碼:文字動(dòng)畫(huà)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市色解,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冒签,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刚梭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡票唆,警方通過(guò)查閱死者的電腦和手機(jī)朴读,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)走趋,“玉大人衅金,你說(shuō)我怎么就攤上這事〔净停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵姨伟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瞒渠,道長(zhǎng),這世上最難降的妖魔是什么伍玖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮串纺,結(jié)果婚禮上仔燕,老公的妹妹穿的比我還像新娘造垛。我一直安慰自己晰搀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布杆逗。 她就那樣靜靜地躺著鳞疲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尚洽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天癣疟,我揣著相機(jī)與錄音潮酒,去河邊找鬼睛挚。 笑死急黎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的勃教。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼遭贸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼心软!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起删铃,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎咒劲,沒(méi)想到半個(gè)月后诫隅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體腐魂,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蛔屹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年豁生,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甸箱。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖豪嗽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情龟梦,我是刑警寧澤肯适,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站框舔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏刘绣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一福贞、第九天 我趴在偏房一處隱蔽的房頂上張望停士。 院中可真熱鬧挖帘,春花似錦完丽、人聲如沸拇舀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至抠璃,卻和暖如春脱惰,著一層夾襖步出監(jiān)牢的瞬間搏嗡,已是汗流浹背枪芒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纽甘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓悍赢,卻偏偏與公主長(zhǎng)得像货徙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痴颊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 【Android 動(dòng)畫(huà)】 動(dòng)畫(huà)分類(lèi)補(bǔ)間動(dòng)畫(huà)(Tween動(dòng)畫(huà))幀動(dòng)畫(huà)(Frame 動(dòng)畫(huà))屬性動(dòng)畫(huà)(Property ...
    Rtia閱讀 6,152評(píng)論 1 38
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程蠢棱,因...
    小菜c閱讀 6,404評(píng)論 0 17
  • 1: 獲取控件寬高 控件View有g(shù)etHeight()和getwidth()方法可以獲取寬高,但是如果直接在on...
    自由人是工程師閱讀 1,778評(píng)論 0 0
  • 一糕再、概述 在Android動(dòng)畫(huà)中玉转,總共有兩種類(lèi)型的動(dòng)畫(huà)View Animation(視圖動(dòng)畫(huà))和Property ...
    summer_lz閱讀 747評(píng)論 1 0
  • Animation Animation類(lèi)是所有動(dòng)畫(huà)(scale、alpha、translate猾担、rotate)的基...
    四月一號(hào)閱讀 1,916評(píng)論 0 10