Android自定義通知樣式適配

今天是端午節(jié)叉庐,祝大家節(jié)日快樂


這篇文章著實醞釀了許久宏多,一直懶得寫。網(wǎng)上關(guān)于通知欄樣式適配的文章很多嗦随,但還不夠完美列荔,這也是我寫這篇文章的動力所在。

溫故而知新


Android通知有兩種枚尼,默認通知與自定義通知贴浙。默認通知簡單調(diào)用系統(tǒng)接口就能實現(xiàn),如下:

發(fā)送默認通知
默認通知效果

自定義通知就稍微麻煩一些署恍,需要定義一個layout文件崎溃,使用RemoteViews加載它并設(shè)置一些點擊事件,再設(shè)置到builder盯质,如下:

自定義通知代碼
自定義通知效果

這個通知很簡單袁串,就是兩行文本加上一個按鈕概而,按鈕具有單獨的點擊事件,點擊后跳轉(zhuǎn)到AnotherActivity囱修。

注意:smallIcon對于自定義通知和默認通知都是必須的赎瑰,否則通知顯示不出來。道理很簡單蔚袍,smallIcon需要在狀態(tài)欄上顯示乡范,不設(shè)置怎么行。在5.0及以上啤咽,smallIcon必須符合Material Design風(fēng)格晋辆,即白色內(nèi)容,透明背景宇整。不然系統(tǒng)會使用默認的圖片替換瓶佳。具體可參考Android通知欄微技巧,那些你所沒關(guān)注過的小細節(jié) 標簽: android通知通知欄微技巧鳞青。后面我會有一篇更詳細的文章來介紹這個霸饲。contentIntent對于2.3及以下的系統(tǒng)是必須的,否則發(fā)送通知時會拋異常臂拓。道理也很簡單厚脉,Android 2.3及以下系統(tǒng)不支持給自定義通知上的元素綁定單獨的點擊事件,因此必須設(shè)置整個通知的點擊事件胶惰。

為什么要進行樣式適配傻工?


默認通知不存在樣式適配的問題,因為默認通知的布局孵滞、顏色中捆、背景什么的都是系統(tǒng)的,系統(tǒng)總會正確的顯示默認通知坊饶。但自定義通知就不一樣了泄伪,自定義通知的布局完全由我們自己掌控,我們可以為元素設(shè)置任何背景匿级、顏色蟋滴。那么,問題來了根蟹。Android通知欄的背景各種各樣脓杉,不同的ROM有不同的背景,白色简逮、黑色球散、透明等。不同的Android版本通知欄背景也不一樣散庶,一旦我們?yōu)樽远x通知上的元素設(shè)置了特定背景或顏色蕉堰,就肯定會帶來兼容性問題(主要是文本啦)凌净。這樣的應(yīng)用一大把,貼個圖大家就明白了:

未適配的自定義通知

怎么適配屋讶?


適配的方式大概有兩種冰寻,一種簡單粗暴:為自定義通知設(shè)置固定的背景(上圖中的360衛(wèi)士就這么干的),比如黑色皿渗。那么內(nèi)容自然就是白色或近似白色斩芭。這樣,在所有的手機上都能正常顯示乐疆,不會出現(xiàn)在黑色背景通知欄上顯示良好划乖,到了白色背景通知欄上就幾乎啥也看不見。使用這種方案的應(yīng)用太多了挤土。我個人很不推崇這種方式琴庵,這樣會使得自定義通知在將近一半的手機上顯示得很突兀,和系統(tǒng)的通知欄不夠沉浸仰美,影響整體美觀迷殿。另一種方案就稍微合理一些:通過讀取系統(tǒng)的通知欄樣式文件,獲取到title和content的顏色咖杂,進而將這個顏色設(shè)置到自定義通知上庆寺。讀取通知欄樣式文件本身有兼容性問題,不同Android版本的樣式文件有變诉字,具體可參考這篇博客 通知欄設(shè)置系統(tǒng)字體顏色 止邮,這種方式也不是在所有手機上生效,實際測試發(fā)現(xiàn)奏窑,還是有小部分機型沒法讀取或是讀取到的是錯誤的。拿到title和content的顏色后屈扎,還可以通過算法(后面細說)判斷這個顏色是近似白色還是近似黑色埃唯,進而能判斷出通知欄的背景是近似黑色還是近似白色,這樣就能根據(jù)不同的通知欄背景加載不同的自定義通知布局鹰晨。進而做到良好的適配墨叛。

更好的適配


現(xiàn)在切入主題,談?wù)勅绾蝸砀玫倪m配自定義通知模蜡。有過鎖屏開發(fā)經(jīng)驗的人應(yīng)該知道漠趁,如果你的應(yīng)用有讀取系統(tǒng)通知欄的權(quán)限,那么每當(dāng)應(yīng)用程序發(fā)出一個通知忍疾,你的應(yīng)用都會收到對應(yīng)的notification對象闯传,這個時候,我們一般會執(zhí)行以下操作:

獲取并展示app通知

調(diào)用addView之后卤妒,應(yīng)用程序的通知就會顯示在我們的應(yīng)用里甥绿。顯然字币,上面的代碼并沒有對apply返回的notificationItemLayout做任何其他操作,但確實這個View顯示出來時就是樣式良好的共缕,可見洗出,notificationItemLayout本身就是帶有樣式的,即便是默認通知图谷。那么方案來了翩活!我們先構(gòu)造一個默認通知:

獲取通知欄title的顏色

通知并不發(fā)送出去,只是用來獲取通知欄title的顏色便贵,如果你還想獲取content的顏色菠镇,抱歉,不能通過查找android.R.id.text來獲取嫉沽,這個字段是訪問不到的辟犀。可通過反射獲取绸硕,更好的辦法是先預(yù)先設(shè)置一個content堂竟,然后遍歷viewGoup根據(jù)content內(nèi)容找到對應(yīng)的TextView再獲取顏色。

拿到顏色后玻佩,可根據(jù)算法判斷這個顏色是近似白色還是近似黑色出嘹,我們使用黑色作為基準色,使用方差來計算這個顏色是否近似黑色:

比較兩個顏色是否近似

baseColor傳入Color.BLACK咬崔,color傳入剛剛獲取到的title的顏色税稼,根據(jù)我實測,閾值為180.0較為合理垮斯。上述方法返回true郎仆,即表示title的顏色近似黑色,也就是說通知欄背景近似白色兜蠕。

額扰肌,經(jīng)驗豐富的同學(xué)應(yīng)該已經(jīng)洞察到第二段代碼存在的兼容性問題了:根據(jù)android.R.id.title去找到title對應(yīng)的TextView是不靠譜的,因為有些ROM廠商會把id改掉熊杨,導(dǎo)致找到的title為空曙旭。

同時還有另外一個問題:使用上述方法,Activity不能繼承自AppCompatActivity(實測5.0以下機型可以晶府,5.0及以上機型不行)桂躏,大致的原因是默認通知布局文件中的ImageView(largeIcon和smallIcon)被替換成了AppCompatImageView,而在5.0及以上系統(tǒng)中川陆,AppCompatImageView的setBackgroundResource(int)未被標記為RemotableViewMethod剂习,導(dǎo)致apply時拋異常。

為了解決這兩個問題,我們改進getNotificationColor方法:

改進后的方法

在getNotificationColorInternal中进倍,設(shè)置一個默認的title文本土至,如果根據(jù)id找不到title,則遍歷notificationRoot根據(jù)設(shè)置的title文本找到title:

兼容廠商改id

在getNotificationColorCompat中猾昆,我們先構(gòu)造一個默認通知陶因,獲取到默認通知的布局文件id,并將布局加載到notificationRoot垂蜗,此時楷扬,如果根據(jù)id找不到title,顯然設(shè)置默認title的辦法已經(jīng)失效了贴见。如何從notificationRoot中找到title是個問題烘苹。我的解決辦法是:反正都已經(jīng)拿到notificationRoot了,不如就遍歷它片部,先找到其中的所有TextView镣衡,取字體最大的TextView作為title(這是合理的,因為默認通知中最多也就4個TextView档悠,分別是title廊鸥、content、info辖所、when惰说,title肯定是字體最大,最顯眼的)缘回,并返回其顏色:

兼容AppCompatActivity

實際測試


拿到了通知欄背景的顏色后吆视,我們就可以加載不同樣式的布局,達到適配的目的酥宴。代碼如下:

適配代碼

效果:

Android 4.4黑色背景的通知欄


堅果手機白色版白色通知欄

好了啦吧,我的第一篇技術(shù)博客到此為止,大家假期玩得Happy拙寡!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丰滑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子倒庵,更是在濱河造成了極大的恐慌,老刑警劉巖炫刷,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擎宝,死亡現(xiàn)場離奇詭異,居然都是意外死亡浑玛,警方通過查閱死者的電腦和手機绍申,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人极阅,你說我怎么就攤上這事胃碾。” “怎么了筋搏?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵仆百,是天一觀的道長。 經(jīng)常有香客問我奔脐,道長俄周,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任髓迎,我火速辦了婚禮峦朗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘排龄。我一直安慰自己波势,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布橄维。 她就那樣靜靜地躺著尺铣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挣郭。 梳的紋絲不亂的頭發(fā)上迄埃,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音兑障,去河邊找鬼侄非。 笑死,一個胖子當(dāng)著我的面吹牛流译,可吹牛的內(nèi)容都是我干的逞怨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼福澡,長吁一口氣:“原來是場噩夢啊……” “哼叠赦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起革砸,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤除秀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后算利,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體册踩,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年效拭,在試婚紗的時候發(fā)現(xiàn)自己被綠了暂吉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胖秒。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖慕的,靈堂內(nèi)的尸體忽然破棺而出阎肝,到底是詐尸還是另有隱情,我是刑警寧澤肮街,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布张肾,位于F島的核電站淆游,受9級特大地震影響苛萎,放射性物質(zhì)發(fā)生泄漏缎浇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一熔号、第九天 我趴在偏房一處隱蔽的房頂上張望稽鞭。 院中可真熱鬧,春花似錦引镊、人聲如沸朦蕴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吩抓。三九已至,卻和暖如春赴恨,著一層夾襖步出監(jiān)牢的瞬間疹娶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工伦连, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雨饺,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓惑淳,卻偏偏與公主長得像额港,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子歧焦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫移斩、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理绢馍,服務(wù)發(fā)現(xiàn)向瓷,斷路器,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 《風(fēng)》 我是一陣永不停歇的風(fēng) 可能有些粗獷 因為我會 吹掉月亮的一層偽裝 吹起街角的一縷彷徨 你需要知道 即...
    時間化成了煙閱讀 200評論 0 2
  • 一舰涌、基本語法 1.1 關(guān)鍵字 1.2 標識符 1.3 變 量 1.3.1猖任、變量的概念: 1.3.2、變量的分類 ...
    鴆羽千夜92閱讀 770評論 0 1