Android 動(dòng)態(tài)實(shí)現(xiàn)圓角背景和圖標(biāo)換色小技巧

前言

不知道你們有沒(méi)有遇到這樣一種場(chǎng)景:

設(shè)計(jì)師:“首頁(yè)這個(gè)按鈕圓角度數(shù)為5個(gè)像素”

你:“OK”疮方,言語(yǔ)間你已經(jīng)在drawable目錄下創(chuàng)建了一個(gè)xml文件工三,定義了圓角的shape襟齿,然后給Imageview設(shè)置上:

<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#f1de11"/>
    <corners android:radius="5px"/>
</shape>

過(guò)了5分鐘……

設(shè)計(jì)師:頂部的Tab選中時(shí)的背景也給它紅色圓角8像素吧

你:“可以”伍玖。反正舉手之勞悴务,再建個(gè)xml就好了”

過(guò)了一會(huì)兒ui復(fù)審…

設(shè)計(jì)師:“新消息提醒改成小圓形吧”

你內(nèi)心:Orz…再這么建下去…

?
開(kāi)個(gè)玩笑享幽,不過(guò)確實(shí)很多時(shí)候我們的項(xiàng)目中會(huì)存在很多圓角背景的ui铲掐,而且一般都還每個(gè)地方的圓角度數(shù)都略有差別,這種時(shí)候是不是內(nèi)心有一種特別想動(dòng)態(tài)更改xml的屬性的沖動(dòng)(不然每個(gè)都對(duì)應(yīng)一個(gè)文件到時(shí)候豈不是一堆)值桩,既然xml不可以摆霉,何不試一下代碼上動(dòng)態(tài)生成呢?

?


動(dòng)態(tài)實(shí)現(xiàn)圓角背景

我們都知道ImageView可以設(shè)置Drawable奔坟,如果我們動(dòng)態(tài)生成一個(gè)圓角的Drawable豈不美哉携栋,恰好Android中有這么一個(gè)類GradientDrawable,它繼承于Drawable蛀蜜,提供了各種shape標(biāo)簽的屬性設(shè)置接口刻两,轉(zhuǎn)換成對(duì)應(yīng)形態(tài)的Drawable對(duì)象。因此我們可以定義這么一個(gè)方法滴某,只需傳入圓角度數(shù)磅摹、顏色和邊緣寬度滋迈,以及是否填充,即可得到一個(gè)等同于xml效果的Drawable資源對(duì)象:

public static GradientDrawable getRoundRectDrawable(int radius, int color, boolean isFill, int strokeWidth){
        //左上户誓、右上饼灿、右下、左下的圓角半徑
        float[] radius = {radius, radius, radius, radius, radius, radius, radius, radius};
        GradientDrawable drawable = new GradientDrawable();
        drawable.setCornerRadii(radius);
        drawable.setColor(isFill ? color : Color.TRANSPARENT);
        drawable.setStroke(isFill ? 0 : strokeWidth, color);
        return drawable;
}

?
使用:

 ImageView imageView = findViewById(R.id.image_view);
 imageView.setBackground(ShapeUtils.getRoundRectDrawable(40, Color.parseColor("#5bc0de"), true, 10));

?
效果如圖:


動(dòng)態(tài)生成圓角圖

就再也不用因?yàn)槟硞€(gè)小屬性的差別而新建那么多的xml文件帝美,既減少了apk的體積碍彭,又便于統(tǒng)一管理和替換,因此可根據(jù)實(shí)際需要可采用動(dòng)態(tài)方式和靜態(tài)方式相結(jié)合悼潭。(此處只是舉例最簡(jiǎn)單的shape例子庇忌,其它屬性設(shè)置可參見(jiàn)API或文末Github地址)

?

動(dòng)態(tài)圖標(biāo)換色

另外一種場(chǎng)景,就是很多app都會(huì)有底部tab用于切換主功能舰褪,當(dāng)前選中的那個(gè)tab的圖標(biāo)肯定和其他未被選中的tab的圖標(biāo)不一樣皆疹,有些是做了一些動(dòng)畫(huà)效果并且對(duì)圖標(biāo)細(xì)節(jié)進(jìn)行了一定調(diào)整,另外一些是圖標(biāo)無(wú)論是否被選中占拍,都是那樣的形狀略就,只是單純換了個(gè)顏色,這種情況我們一般會(huì)讓ui再另外切一套著色了的圖標(biāo)晃酒,然后代碼中動(dòng)態(tài)切換圖標(biāo)表牢,達(dá)到切換tab的效果。但這種方式同樣存在一個(gè)問(wèn)題贝次,兩套一摸一樣的圖標(biāo)崔兴,只是顏色不一樣,這樣會(huì)不會(huì)有點(diǎn)占用apk體積浊闪,是否可以通過(guò)動(dòng)態(tài)給Icon涂上顏色呢恼布?

答案是可以的,同樣是通過(guò)Drawable來(lái)操作搁宾,圖標(biāo)本身可以通過(guò)getDrawable轉(zhuǎn)換為Drawable對(duì)象折汞,然后再通過(guò)DrawCompat來(lái)進(jìn)行重新著色:

 /**
     * 將drawable顏色著色為color
     * @param drawable
     * @param color
     * @return 重繪后的Drawable
     */
    public static Drawable drawColor(Drawable drawable, int color) {
        final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
        wrappedDrawable.mutate();
        DrawableCompat.setTint(wrappedDrawable, color);
        return wrappedDrawable;
    }

?
首先DrawableCompat.wrap是將drawable轉(zhuǎn)換為可著色的Drawable對(duì)象,然后調(diào)用mutate是表示只對(duì)當(dāng)前這個(gè)對(duì)象進(jìn)行著色盖腿,假如不調(diào)用這句爽待,到時(shí)候一著完色,以后再getDrawable獲取這個(gè)對(duì)象的時(shí)候翩腐,就都變成著色后的了(即拿不到之前原來(lái)的那個(gè)Drawable了)鸟款,然后setTint就是將我們想要重繪的顏色繪制上去了,最后將新的Drawable返回茂卦,同樣設(shè)置給ImageView何什,就可以變成另外一個(gè)顏色的Icon了。

弄了個(gè)簡(jiǎn)單的動(dòng)畫(huà)等龙,不斷對(duì)icon進(jìn)行染色:

final ImageView imageView = findViewById(R.id.image_view);
ValueAnimator animator = ValueAnimator.ofArgb(Color.parseColor("#3F51B5"),Color.parseColor("#FF4081"));
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int color = (int)animation.getAnimatedValue();
                imageView.setBackground(ShapeUtils.drawColor(getResources().getDrawable(R.drawable.ic_android), color));
            }
});

?
效果如圖:


圖標(biāo)染色

?

總結(jié)

這兩種方式有時(shí)候在特別多重復(fù)但卻有略微差別的ui場(chǎng)景中可以派上用場(chǎng)处渣,另外還可以用來(lái)統(tǒng)一控制某些圖標(biāo)的顏色或者多個(gè)圓角的控制伶贰,具體結(jié)合實(shí)際情況進(jìn)行運(yùn)用。
這里只是列舉了幾個(gè)shape的常用屬性罐栈,它還有其他很多屬性可以動(dòng)態(tài)設(shè)置黍衙,把它們封裝成了一個(gè)工具類,代碼已傳到 GitHub-ZJYWidget 荠诬。里面有很多實(shí)用的自定義View源碼及demo琅翻,會(huì)長(zhǎng)期維護(hù),歡迎Star~ 如有不足之處或建議還望指正柑贞,相互進(jìn)步方椎,如果覺(jué)得不錯(cuò)動(dòng)動(dòng)小手給個(gè)喜歡, 謝謝~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凌外,一起剝皮案震驚了整個(gè)濱河市辩尊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌康辑,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轿亮,死亡現(xiàn)場(chǎng)離奇詭異疮薇,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)我注,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)按咒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人但骨,你說(shuō)我怎么就攤上這事励七。” “怎么了奔缠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵掠抬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我校哎,道長(zhǎng)两波,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任闷哆,我火速辦了婚禮腰奋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抱怔。我一直安慰自己劣坊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布屈留。 她就那樣靜靜地躺著局冰,像睡著了一般测蘑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锐想,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天帮寻,我揣著相機(jī)與錄音,去河邊找鬼赠摇。 笑死固逗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的藕帜。 我是一名探鬼主播烫罩,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洽故!你這毒婦竟也來(lái)了贝攒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤时甚,失蹤者是張志新(化名)和其女友劉穎隘弊,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體荒适,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梨熙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刀诬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咽扇。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖陕壹,靈堂內(nèi)的尸體忽然破棺而出质欲,到底是詐尸還是另有隱情,我是刑警寧澤糠馆,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布嘶伟,位于F島的核電站,受9級(jí)特大地震影響榨惠,放射性物質(zhì)發(fā)生泄漏奋早。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一赠橙、第九天 我趴在偏房一處隱蔽的房頂上張望耽装。 院中可真熱鬧,春花似錦期揪、人聲如沸掉奄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)姓建。三九已至诞仓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間速兔,已是汗流浹背墅拭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涣狗,地道東北人谍婉。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像镀钓,于是被迫代替她去往敵國(guó)和親穗熬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程丁溅,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 概述 今天我們來(lái)探究一下android的樣式唤蔗。其實(shí),幾乎所有的控件都可以使用 background屬性去引用自定義...
    CokeNello閱讀 4,813評(píng)論 1 19
  • 很早看過(guò)這篇文章窟赏,并做了筆記妓柜,后來(lái)看到群里的小伙伴有問(wèn)相關(guān)Drawable的問(wèn)題,就把這篇翻譯過(guò)來(lái)的文章給放出來(lái)了...
    Kotyo閱讀 1,418評(píng)論 0 5
  • 一、前言 在 Android 的開(kāi)發(fā)過(guò)程中诉稍,Drawable 經(jīng)常會(huì)被用到蝠嘉,一般會(huì)用 Drawable 為 Vie...
    承香墨影閱讀 889評(píng)論 1 16
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件杯巨、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,024評(píng)論 4 62