Android 自定義陰影

最近在項目碰到一個比較頭疼的項目,設(shè)計師需要給ui圖中的一些按鈕之類的東西添加陰影街图。乍一看設(shè)計圖阻荒,這沒啥嘛,咱們Android中不是有這個屬性嘛漩怎,于是擼起袖子開搞:

<TextView
android:id="@+id/btn_test_performance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="5dp"
android:text="@string/hello"
android:background="@drawable/shape_round_white"
android:padding="20dp"
android:layout_marginTop="10dp"
android:layout_gravity="center"/>

圖1

代碼敲完跑起來看一下效果圖勋颖,恩,效果還可以勋锤。于是把所有需要陰影的控件全部加上android:elevation屬性饭玲,美滋滋,有api就是好叁执。事情發(fā)展得很順利茄厘,直到我們設(shè)計師找到我,“你是Android設(shè)計師吧谈宛,你這個顏色有點不對啊次哈,我們標記的顏色比較淡,你這個顏色有點深”吆录。窑滞。。瞬間凌亂,wtf,這個顏色是系統(tǒng)自帶的啊哀卫,我怎么控制巨坊。于是上網(wǎng)google一下,怎樣修改elevation的顏色屬性此改。一頓搜索后趾撵,無果。禍不單行共啃,我們測試工程師也找了過來占调,“你這個頁面不對啊,我們設(shè)計圖上這里有陰影勋磕,你這里啥也沒有”妈候。?挂滓?苦银?什么鬼,不可能啊赶站,我這里都有的幔虏,你這個包有問題吧。于是把測試的測試機拿過來自己裝上一個一跑贝椿。想括。。尼瑪烙博,什么鬼瑟蜈,真沒有≡埽回頭再看一遍自己的代碼發(fā)現(xiàn)在android:elevation上有一個黃色的警告铺根,之前沒注意,鼠標放上去一看乔宿,


圖2

位迂。。原來是版本適配問題详瑞,看來是api是不能用了掂林,只能通過一些其他的手段去實現(xiàn)了。經(jīng)過漫長的思考人生后坝橡,想出下面幾個思路:

  1. 自定義shape.xml drawable文件去給控件設(shè)置背景泻帮,使用Gradient漸變色屬性實現(xiàn)陰影樣式。
  2. 找ui設(shè)計師驳庭,讓他們切一個帶陰影的圖給我們(找ui能解決的都不是事~)
  3. 自己代碼實現(xiàn)一個帶背景的自定義view

經(jīng)過不停地自我推翻以及方案被否定后還是留下了第三個方案刑顺,主要原因如下:

  • 第一個方案的漸變色不支持四周向中間的漸變氯窍,只能支持線性或者環(huán)裝形式漸變饲常,這兩種都不滿足需要蹲堂,因為陰影本身是一個四周一層很淡的顏色包圍,在一個矩形框的層面上顏色大概一致贝淤,所以這個思路無法實現(xiàn)這個需求柒竞,拋棄。
  • 第二個方案詢問了一下我們ui播聪。朽基。他們給出的結(jié)果是如果使用切圖的話那標注的話很難標,身為一個優(yōu)秀的設(shè)計師大多對像素點都和敏感离陶,界面上的像素點有一點不協(xié)調(diào)那都是無法容忍的稼虎。。
  • 那么就只剩下第三個方案了

經(jīng)過資料查詢招刨,發(fā)現(xiàn)有兩個方式用來寫陰影很合適霎俩。在我們Android中自定義view的時候有以下兩個方法,我們可能用的都不是很多:

  1. paint.setShadowLayer(float radius, float dx, float dy, int shadowColor);
    這個方法可以達到這樣一個效果沉眶,在使用canvas畫圖時給視圖順帶上一層陰影效果打却。
    簡單介紹一下這幾個參數(shù):
    radius: 陰影半徑,主要可以控制陰影的模糊效果以及陰影擴散出去的大小谎倔。
    dx:陰影在X軸方向上的偏移量
    dy: 陰影在Y軸方向上的偏移量
    shadowColor: 陰影顏色柳击。
    終于找到了設(shè)置顏色的,通過設(shè)置shadowColor來控制視圖的陰影顏色片习。
    我們試一下使用paint.setShadowLayer(10, 0, 0, Color.RED)的效果:


    圖3

    這個是在4.1的設(shè)備上的效果圖捌肴,上面的hello world使用elevation,可以看到絲毫沒有效果藕咏。下面是使用自定義view的方式畫出來的一個圖状知,可以看到效果是很nice的,這個也實現(xiàn)了顏色的可調(diào)整性侈离,完美解決试幽。

這里也順帶說下第二種思路,這邊我試了一下效果沒這邊好卦碾,有可能是我沒調(diào)整好铺坞,個人覺得應(yīng)該也是能實現(xiàn)這種效果的, paint還有一個方法是paint.setMaskFilter();這里通過設(shè)置BlurMaskFilter()應(yīng)該也能達到這種效果洲胖。

對于第一種方案济榨,經(jīng)過思考決定封裝成一個Viewgroup比較合適,將需要設(shè)置陰影的視圖放到Viewgroup里面绿映。其中涉及到幾個屬性擒滑,陰影的寬度腐晾,view到Viewgroup的距離,如果視圖和父布局一樣大的話丐一,那陰影就不好顯示藻糖,如果要能夠顯示出來就必須設(shè)置clipChildren=false。還有就是視圖自帶的圓角库车,大部分背景都是有圓角的巨柒,比如上圖中的圓角,需要達到高度還原陰影的效果就是的陰影的圓角和背景保持一致柠衍。
這里把這幾個屬性抽成自定義屬性:

<declare-styleable name="ShadowContainer">
<attr name="containerShadowColor" format="color"/>
<attr name="containerShadowRadius" format="dimension"/>
<attr name="containerDeltaLength" format="dimension"/>
<attr name="containerCornerRadius" format="dimension"/>
<attr name="deltaX" format="dimension"/>
<attr name="deltaY" format="dimension"/>
</declare-styleable>

  • containerShadowColor:設(shè)置陰影顏色
  • containerShadowRadius:設(shè)置陰影的擴展距離
  • containerDeltaLength:設(shè)置子View到ShadowContainer的距離
  • containerCornerRadius:設(shè)置子View背景的圓角大小
  • deltaX: 設(shè)置陰影向下移動距離
  • deltaY: 設(shè)置陰影在Y軸移動距離


    圖4

    這里使用畫圖的方式解釋一下這幾個參數(shù):
    圖中的紅色區(qū)域是需要設(shè)置陰影的View洋满,外部黑色邊框包裹的區(qū)域是ShadowContainer,中間的白色部分是陰影展示的區(qū)域珍坊,這塊的大小根據(jù)設(shè)置的containerDeltaLength控制牺勾。這里打個比方,如果目標view需要距離左邊20dp的話阵漏,而中間的containerdeltaLength為10dp驻民,則只需要將ShadowContainer的marginLeft設(shè)置為10dp就可以了,這樣可以完美控制子view的位置袱饭。

此外川无,containerShadowRadius影響的是陰影在空白區(qū)域的占比情況,如果containerShadowRadius小一點的話陰影倒是不大, 但是如果太大的話那么空白區(qū)域可能裝不下陰影面積虑乖。這里需要看情況調(diào)整懦趋。

使用方式:

<example.chenj.com.apptest.ShadowContainer
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_gravity="center"
app:containerCornerRadius="5dp"
app:containerDeltaLength="5dp"
app:containerShadowColor="#f00"
app:containerShadowRadius="5dp">
<View
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/shape_round_white"/>
</example.chenj.com.apptest.ShadowContainer>

效果圖:


圖5
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市疹味,隨后出現(xiàn)的幾起案子仅叫,更是在濱河造成了極大的恐慌,老刑警劉巖糙捺,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诫咱,死亡現(xiàn)場離奇詭異,居然都是意外死亡洪灯,警方通過查閱死者的電腦和手機坎缭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來签钩,“玉大人掏呼,你說我怎么就攤上這事∏﹂荩” “怎么了憎夷?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長昧旨。 經(jīng)常有香客問我拾给,道長祥得,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任蒋得,我火速辦了婚禮级及,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘窄锅。我一直安慰自己创千,他們只是感情好缰雇,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布入偷。 她就那樣靜靜地躺著,像睡著了一般械哟。 火紅的嫁衣襯著肌膚如雪疏之。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天暇咆,我揣著相機與錄音锋爪,去河邊找鬼。 笑死爸业,一個胖子當著我的面吹牛其骄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扯旷,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼拯爽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钧忽?” 一聲冷哼從身側(cè)響起毯炮,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耸黑,沒想到半個月后桃煎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡大刊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年为迈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缺菌。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡葫辐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出男翰,到底是詐尸還是另有隱情另患,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布蛾绎,位于F島的核電站昆箕,受9級特大地震影響鸦列,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹏倘,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一薯嗤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纤泵,春花似錦骆姐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至公荧,卻和暖如春带射,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背循狰。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工窟社, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绪钥。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓灿里,卻偏偏與公主長得像,于是被迫代替她去往敵國和親程腹。 傳聞我的和親對象是個殘疾皇子匣吊,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

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