[Swift]Metronome #2 Custom UIButton 自訂有兩層陰影的Button

Penny N.
8 min readJun 29, 2020

--

Photo by James Stamler on Unsplash

幫忙設計的朋友這次在元件上使用了很多陰影效果,利用白色與黑色的陰影製造出立體感。原本考慮直接用Zeplin將元件匯出為圖檔,放入button使用,卻發現button點選後改變的圖樣被設計為沒有外陰影,若將所有button匯出為圖檔使用,會造成顯示在button時,有陰影的button看起來比較小。

身為一個稱職的工程師,還是要想辦法實現設計師的設計!所以嘗試了自訂button型別,讓button擁有白色及黑色的兩種陰影,而且在button按下、狀態改變時,會依據目前的狀態來顯示或隱藏陰影!

Double Shadows

要為一個元件做出兩個陰影是第一個考驗。

第一個想到的解法是在元件底下加上一個view,仿照元件的大小、圓角,做出反方向、不同顏色的陰影。這個方法簡單很多,但卻會讓code file上多出很多IBOutlet和設定view的code。

後來參考Multiple shadows under UIView iOS Swift做出了兩層陰影。

這個方法是客製化一個繼承UIButton的型別,在subclass中建立兩個CALayer的物件,分別為兩種顏色的陰影layer,然後在layoutSubviews中設定兩個layer的大小、顏色、圓角、陰影等等,最後透過insertSublayer將兩個layer加入在最底層。

這個方法成功讓每個button都擁有黑白兩種顏色的陰影,但又讓我面臨了戲下一個問題——因為將陰影設定在layoutSubviews,接下來MainVC無法根據按鈕是否按下來調整陰影顯示或隱藏,導致播放按鈕及聲音按鈕按下,周圍的陰影仍然存在。

Remove and Add Shadows According to Button Status

這問題讓我苦惱了好一陣子,百思不得其解,決定實行Coursera名課Learning How to Learn所教授的方法,讓自己的大腦進入diffuse mode(其實就只是追劇XD)。看了幾分鐘Snowpiercer靈感竟然源源不絕湧出!

後來決定在init中設定所有陰影相關的設定,如此一來所有繼承這個subclass的button生來就有兩道陰影。

另外查到如果是用storyboard建立button,就要使用init?(coder aDecoder: NSCoder)來設定初始值。

透過客製化一個function hideShadow(),讓繼承這個subclass的button可以透過呼叫它來隱藏或顯示兩個陰影的layer。

soundOnButtonOutlet.hideShadow(player.isMuted ? true : false)

layoutSubviews中則保留所有不會改變到的設定,例如button上的文字顏色、insertSublayer將兩個陰影layer加入最底層。

這樣就成功做出了自己想要的效果!

按鈕未按下(左),按鈕按下(右)

References:

Initializer

CAlayer

Programming iOS 13: Dive Deep into Views, View Controllers, and Frameworks By Matt Neuburg

CAShapeLayer

UIView.layoutSubviews

UIView Shadow

Custon Button

Button Image

--

--

Penny N.
Penny N.

Written by Penny N.

A passionate self-taught  iOS developer. Write to record my learning and share the knowledge

No responses yet