幫忙設計的朋友這次在元件上使用了很多陰影效果,利用白色與黑色的陰影製造出立體感。原本考慮直接用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加入最底層。
這樣就成功做出了自己想要的效果!
[Swift]Metronome #1 Protocol & Delegate, Singleton
[Swift]Metronome #3 Glowing Animation發光動畫效果
[Swift]Metronome #4 Popover 選取視窗, Google AdMob
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