要調幾次、隨機、重來都可以!恐龍的帽子調色進階版─調色大師 APP

◆課堂練習&作業10–1:調色大師─Outlet & Action+亂數應用◆

繼之前練習過的 在 Playground 去背調色 之後,這次是更進階的練習, 結合 IBOutlet 跟 IBAction 的應用客製化整張圖片 (ง๑ •̀_•́)ง
不只可以隨時改變帽子顏色,背景色、圓角、陰影、邊框全都可以調整到滿意為止!

製作內容:
1.利用 Slider 調整顏色&Label 顯示顏色數值
2. 多個區塊的調色(利用 Segmented Control 控制)
3.加入顏色隨機按鈕(random)及重新調色按鈕
4.利用 Slider 調整圖片的圓角、陰影、邊框
5.設定 Switch可用/不可用、打開 Switch 時才顯示可用的按鈕或是 Slider
6.用按鈕將花紋加到圖片上
7.應用寫在外面的變數來儲存東西

成品

做動作的時候 GIF 畫面一直破圖 (┛`д´)┛ 下次用錄影的好了 (´c_`)

製作記錄:外觀部分

【設置按鈕邊框顏色】

直接輸入 layer.borderColor 、Type 設為 Color 選色後仍然跑不出邊框顏色

常見的邊框色+白色底按鈕(右邊那顆)設置起來卻沒想像中簡單

因為從 Type 設置的 Color 型別是 UIColor,而邊框顏色的型別是用 CGColor,因此要新增一個 file 讓預設的 UIColor 變成邊框需要的 CGColor

步驟 1:點選 File→New→New File(快捷 cmd+N)會跳出下面的視窗,選擇 Objective-C File 後按下一步

步驟 2:第二個視窗,File 名可自行填寫,File Type 選 Category,最下面的 Class 要自己手動輸入 CALayer,輸入完畢後點下一步就創好新的檔案了

這邊已經有是因為做完才重新截圖,原本 Class 右邊三角形點開只會有幾個預設值

步驟 3:此時右邊會多兩個檔案,分別是 xxxx.hxxxx.m點入 xxxx.m 的那個檔案,並貼上下面程式碼

新增的 .h 跟 .m 檔案
#import “CALayer+borderColor.h”
#import <UIKit/UIKit.h>
@implementation CALayer (borderColor)
- (void)setBorderColorWithUIColor:(UIColor *)color
{
self.borderColor = color.CGColor;
}
@end

有部分程式碼其實是創立檔案時就寫好的(例如第一行 #import 跟最後一行 @end ) 但直接整段覆蓋避免出錯比較安全

步驟 4:可以正大光明的在設置的視窗輸入 layer.borderColor 並選色啦!(也要加入 layer.borderWidth 才能有邊框寬度&要開模擬器才看得到)

參考文章:

【同時製作圖片圓角跟陰影】

同時擁有陰影跟圓角,要建立一個新的 view(ShadowView)來設置陰影,並且把要設定圓角的圖片(DinoBackgroundImageView)包在裡面

圖層排列順序

並且將 Shadow View 的 Background Color 需設為白色,陰影的顏色是透過 .layer.shadowColor = UIColor.darkGray.cgColor 這行程式碼來產生,ShadowView 設置的 Background Color 跟陰影顏色無關

設為白色是因為此時圖片(DinoBackgroundImageView)是去背過可以調色的,調色時若把透明度調為 1 以下,如果 ShadowView 的背景設為其他顏色會覆蓋上該顏色,設置為 clear 則會蓋上陰影色(用下面圖片說明比較好懂)

左:ShadowView的背景色要設為白色的原因/右:陰影產生時,如果 Shadowview 的背景色透明度小於 1,會透出陰影的顏色

整體來說需要設置語法的部份為:
【設圓角的 ImageView(DinoBackgroundImageView)
.clipsToBounds = true +圓角語法

【陰影 View(ShadowView)
陰影相關語法(顏色、位置、銳利度等)+圓角語法
陰影的 View 也要設置圓角,這樣圖片在拉圓角時才不會因為被擋住而破圖

製作記錄:功能部分

【IBAction 的語法注意點】

IBAction 中寫觸發哪個元件,裡面的內容就只專注於觸發後的動作

例如:觸發 SwitchOn,裡面的動作就專注寫「開關打開之後會有哪些動作」,不要貪心在裡面寫切換 SegmentControl 會出現的動作

SegmentControl 的切換所觸發的動作就寫在 SegmentControl 的 IBAction 裡,SwitchOn 就只寫開關打開時的動作,程式整體上也比較不混亂

各自有各自的任務要做,不要貪心攬奏匯,會有問題der
會發現自己寫有這個問題,是因為功能設定為:
花色的Switch只有停留在帽子SegmentControl的時候可以使用&開啟,打開後會跑出花紋的按鈕可以選擇。而切換到其他兩個SegmentControl(調整背景&邊框色)時會讓Switch無法使用&開啟,也會隱藏按鈕
但一開始寫程式時卻在SwitchOn這個IBAction裡面,用if寫進切換到其他SegmentControl時的內容,例如Switch無法使用、Button會隱藏等設定,然後就出現了Bug(笑)因為SwitchOn這個IBAction只管開關有沒有開

【花紋設置】

原本想要像〈我家的貓貓最可愛!〉這篇文一樣,使用 tintColor 來改花紋色,但是在無限的卡關後發現了盲點:

雖然可以加上花紋,但是無法調花紋的顏色!因為沒有製作調整花紋顏色用的 Slider(上面的 Slider 動了就會影響帽子顏色,因為他是屬於帽子的調色 Slider)

除非像貓貓文中一樣,純色製作一份調色 Slider、花紋處也製作一份調色 Slider,或是將花紋功能移至其他 SegmentControl,才能製作出調整花紋顏色的功能

最後呈現效果:在帽子上覆蓋一張花紋牌,結束這一回合!
最後放棄調花紋顏色的功能,直接將花紋圖片覆蓋在帽子的顏色上。設定原本圖片的 tintColor,並用灰色系&透明度調低,讓墊在下面的帽子色能透出來一點點這裡不用把花紋墊在底下的方式,是因為如果按了按鈕,若當時帽子的透明度為 1,導致顏色蓋住而看不到花紋,操作上不夠直觀&麻煩(按了就是想要馬上看套花紋上去的效果啊 XD)

【各個顏色的隨機按鈕】

只對紅/綠/藍/透明度單個選項做隨機變動

一開始一直糾結在 UIColor 沒有只改變單個顏色的語法(如果沒有卡住就不會寫進製作記錄XD)後來靈光一閃,那就讓其他沒有要隨機的顏色停留在原本 Slider 的 Value 就好啦!

其實這邊語法很簡單 XD 真的只是一時腦袋打結(因為篇幅關係只貼紅色的部分,其他顏色寫法同理)

【用變數儲存值】

卡最久的部分,這個應用在兩個部分:

  • 因為帽子、背景、邊框在未調色前的預設顏色都不同,想要在切換 SegmentControl 時,顯示預設色在 Slider 上相對應的位置。但是進行調色後,即使切換到其他 SegmentControl 再回來,也會停留在上次調整後的位置
  • 修復花紋 Switch 的 Bug(未修復前:SwitchOn+選花色後,切換到其他 SegmentControl 再回來,雖然花紋還會印在圖上,但是 Switch 會顯示為Off)

利用寫在外面的變數來儲存資料,不管在哪個 function 中都能寫入想要的值或是將變更後的值再存回變數中

宣告的變數總共是這些

1. Slider 部分
因為一個變數只能寫一個值,3 個調色物件(帽子、背景、邊框)各有 4 種值(紅色、綠色、藍色、透明度)所以總共要設置 12 個變數,並且在宣告時先填入該色的預設值,這個預設值是用在「使用者未調色前」會顯示的 Slider 位置

一開始雖然知道變數後面只能寫值,但莫名的腦袋打結不知道該怎麼寫(一直連結 UIColor 寫 RGB 的寫法)其實顏色也是值啊,就是 RGB 的數字,例如:R: 43/255 G: 44/255 B: 243/255,所以才需要各選項各寫一個變數不能共用

另外,Slider 的型別是 Float,所以在寫變數時先改變型別為 Float,就不用之後一直包括號轉換

而顏色的 Slider 值設定在 0~1,這裡用 xx/255 的方式表示是因為寫法更直覺(平常顏色也都是用這種寫法,再讓程式去運算)且之後要換預設色就不用再手動計算一次(直接改寫前面 xx 的值就可以)

這邊語法統一只寫帽子部分,其他同理所以省略

只要有變更值的動作(觸發 IBACtion func colorSliderChange 時就要將新的值存入變數中,再透過 SetValue 的 function 讓 Slider 跳到該值的位置

沒有變更值的時候(使用者未調整顏色,因此不會觸發 IBACtion func colorSliderChange)因為當時變數沒有存入其他值,所以使用預設值呈現

Slider 部分最後呈現效果

文字描述有點複雜,總之在觸發動作前使用預設值(宣告時寫的值),觸發後則存入新的值。就能呈現出想達到的:切換 SegmentControl 時顯示預設顏色的位置,調色後會停留在上次調整後的位置

Switch 部分最後呈現效果,切換到其他欄位後再回來 Switch 還是會維持之前的狀態

2. Switch 部份
容我先跳過,懂歸懂但還無法用好理解的方式寫出來 😂 (光 Slider 那串都覺得像是繞口令 XD)
不過觀念是一樣的:先做一個預設值,觸發其他動作時再去存入新的值,只是這次填入的值 true 或 false 不是數字

【完整程式碼@GitHub】

整篇記錄寫完發現,卡關部分大多因為觀念還不夠清楚,應用上不夠精確才會「想做的功能用程式做出來後,卻沒有達到預期成果」。゚ヽ(゚´Д`)ノ゚。

Coding 完成後,還是覺得有哪邊可以整合成幾行就搞定,例如:各色隨機按鈕部分,落落長但是內容都差不多。礙於時間關係(這篇拖太久 XD)先求有然後還不差就好,等之後功力進步再慢慢簡化,不然作業進度落後太多啦 レ(゚∀゚;)ヘ

最後的反思時間,花紋雖然隨著關閉 Switch 就會消失(當時想說只有兩個花紋,不用特定做清除功能)但是更進階的還能製作:1.按一下跑出花紋,按第兩下花紋消失,按第三下花紋又出現
2.Switch 關閉後再打開,花紋會出現並選擇上次的設置

另外,推薦卡很久的時候換個環境寫看看。之前在家寫卡了好幾天,怎麼想腦袋就是運轉不過來。隔天因為在等空檔跑去咖啡廳寫,兩三小時就把之前卡兩三天的部份都搞定 XD

--

--