『自定義View實(shí)戰(zhàn)』—— 自定義跑馬燈

在工作中難免遇到自定義 View 的相關(guān)需求腋粥,本身這方面比較薄弱蚊荣,因此做個(gè)記錄,也是自己學(xué)習(xí)和成長(zhǎng)的積累秫筏。自定義View實(shí)戰(zhàn)

前言

最近公司接到小需求--「可以滾動(dòng)的提示」诱鞠,其實(shí)就是跑馬燈。這讓我想到了大學(xué)時(shí)專業(yè)物聯(lián)網(wǎng)这敬,當(dāng)時(shí)學(xué)的單片機(jī)入門教程就是跑馬燈航夺,很是親切。其實(shí)就是燈(或文字)按照某個(gè)方向循環(huán)滾動(dòng)崔涂。

Android 原生的跑馬燈

其實(shí)阳掐,Android中的TextView自帶跑馬燈效果,只需要通過簡(jiǎn)單的配置冷蚂,就可以完成滾動(dòng)的效果缭保。

XML中進(jìn)行配置

<TextView
    android:id="@+id/test"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:marqueeRepeatLimit="marquee_forever"
    android:scrollHorizontally="true"
    android:singleLine="true"
    android:text="我是跑馬燈,我是跑馬燈帝雇,我是跑馬燈涮俄,我是跑馬燈,我是跑馬燈尸闸,我是跑馬"
    android:textSize="28sp" />

可以看到需要很多的屬性配置彻亲,了解一下每個(gè)屬性的含義:

  • android:ellipsize="marquee" 設(shè)置為跑馬燈效果
  • android:focusable="true" 獲取焦點(diǎn)
  • android:focusableInTouchMode="true" touch 時(shí)獲取焦點(diǎn)
  • android:marqueeRepeatLimit="marquee_forever" 設(shè)置重復(fù)次數(shù)
  • android:scrollHorizontally="true" 設(shè)置為水平滾動(dòng)
  • android:singleLine="true" 單行顯示

按照上面的配置,正常情況下是可以運(yùn)轉(zhuǎn)的吮廉,但是用到項(xiàng)目中的時(shí)候苞尝,會(huì)發(fā)現(xiàn)很多bug和不足之處。

比如宦芦,偶爾突然不滾動(dòng)了宙址,具體的原因是沒有獲取到焦點(diǎn)。我覺得這是原生跑馬燈最坑的一點(diǎn)调卑,必須獲取到焦點(diǎn)才能正常運(yùn)行抡砂。

當(dāng)然解決方式也有大咱,第一種,通過主動(dòng)獲取焦點(diǎn)的方式注益,即調(diào)用view.setFocusable(true)碴巾。還有一種就是重寫TextViewisFocused()方法,強(qiáng)制讓他獲取焦點(diǎn)丑搔。

@Override
public boolean isFocused() {
    return true;
}

就算這樣厦瓢,在遇到復(fù)雜的界面還是會(huì)遇到問題,要么焦點(diǎn)會(huì)被斷斷續(xù)續(xù)的被搶奪啤月,導(dǎo)致卡頓煮仇,要么不符合UI提出的滾動(dòng)速度要求。

自定義跑馬燈

鑒于這個(gè)背景谎仲,通過Scroller完成自定義的跑馬燈浙垫,代碼已上傳至GitHub上:MarqueeTextView

先看一下整體的效果:

MarqueeTextView

如果想直接使用,在根build.gradle配置:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

app下的build.gradle添加依賴

dependencies {
    compile 'com.github.xiaweizi:MarqueeTextView:1.0'
}

最后在XML直接使用即可:

   <com.xiaweizi.marquee.MarqueeTextView
        android:id="@+id/marquee1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="@string/string1"
        android:textColor="#ff0000"
        android:textSize="18sp"
        app:scroll_first_delay="0"
        app:scroll_interval="2000"
        app:scroll_mode="mode_forever" />

具有一下功能:

  • 控制滾動(dòng)時(shí)間
  • 控制滾動(dòng)延遲
  • 控制滾動(dòng)模式
  • 生命周期可以自己控制
    • 暫停
    • 繼續(xù)
    • 重新開始
    • 停止

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

通過Scroller控制器來控制整個(gè)View的滾動(dòng)强重,那什么是Scroller绞呈,做個(gè)簡(jiǎn)單的介紹。

Scroller內(nèi)部封裝了滾動(dòng)的操作间景,通過構(gòu)造函數(shù)中傳入插值器佃声。可以控制起始位置和整個(gè)滾動(dòng)的時(shí)間倘要,并且通過computeScrollOffset()得到滾動(dòng)動(dòng)作是否結(jié)束圾亏。

最核心的方法有兩個(gè):

  1. startScroll

     /**
      * @param startX 水平方向滾動(dòng)的偏移值,以像素為單位封拧。
      * @param startY 垂直方向滾動(dòng)的偏移值志鹃,以像素為單位
      * @param dx     水平方向滾動(dòng)的距離
      * @param dy     垂直方向滾動(dòng)的距離
      * @param duration 滾動(dòng)持續(xù)的時(shí)間,以毫秒為單位
      */
     public void startScroll (int startX, int startY, int dx, int dy, int duration) {
         ...
     } 
    
  2. computeScrollOffset

     /**
      * @return 返回動(dòng)畫是否結(jié)束
      */
     public boolean computeScrollOffset (){
         ...
     }
    

注釋已經(jīng)很清楚了泽西,那么接下來講一下滾動(dòng)的大概實(shí)現(xiàn)曹铃。

首先,要算出從初始位置開始滾動(dòng)捧杉,到結(jié)束的距離陕见,其實(shí)就是文字的長(zhǎng)度。

/**
 * 計(jì)算滾動(dòng)的距離
 * @return 滾動(dòng)的距離
 */
private int calculateScrollingLen() {
    TextPaint tp = getPaint();
    Rect rect = new Rect();
    String strTxt = getText().toString();
    tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
    return rect.width();
}

其次味抖,調(diào)用startScroll方法進(jìn)行滾動(dòng)评甜,注意的是需要調(diào)用invalidate方法,才會(huì)有效果仔涩。

最后一個(gè)問題就是忍坷,滾動(dòng)結(jié)束后繼續(xù)滾動(dòng)。Scroller在滾動(dòng)的時(shí)候,會(huì)不斷回調(diào)ViewcomputeScroll方法佩研,于是就可以在這個(gè)方法里進(jìn)行判斷柑肴,如果結(jié)束了,就重新開始韧骗。

到此一個(gè)簡(jiǎn)單的跑馬燈效果就實(shí)現(xiàn)了嘉抒,當(dāng)然如果還想添加別的需要零聚,只要搞懂其原理袍暴,這些都不是問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末隶症,一起剝皮案震驚了整個(gè)濱河市政模,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚂会,老刑警劉巖淋样,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異胁住,居然都是意外死亡趁猴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門彪见,熙熙樓的掌柜王于貴愁眉苦臉地迎上來儡司,“玉大人,你說我怎么就攤上這事余指〔度” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵酵镜,是天一觀的道長(zhǎng)碉碉。 經(jīng)常有香客問我,道長(zhǎng)淮韭,這世上最難降的妖魔是什么垢粮? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮靠粪,結(jié)果婚禮上蜡吧,老公的妹妹穿的比我還像新娘。我一直安慰自己庇配,他們只是感情好斩跌,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捞慌,像睡著了一般耀鸦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天袖订,我揣著相機(jī)與錄音氮帐,去河邊找鬼。 笑死洛姑,一個(gè)胖子當(dāng)著我的面吹牛上沐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播楞艾,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼参咙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了硫眯?” 一聲冷哼從身側(cè)響起蕴侧,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎两入,沒想到半個(gè)月后净宵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡裹纳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年择葡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剃氧。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敏储,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出她我,到底是詐尸還是另有隱情虹曙,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布番舆,位于F島的核電站酝碳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恨狈。R本人自食惡果不足惜疏哗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望禾怠。 院中可真熱鬧返奉,春花似錦、人聲如沸吗氏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弦讽。三九已至污尉,卻和暖如春膀哲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悼做,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓兴喂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親焚志。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衣迷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

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