Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
20180710_iOSLT_iOSでDarkModeを実装する
Search
shtnkgm
July 10, 2018
Programming
120
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
20180710_iOSLT_iOSでDarkModeを実装する
shtnkgm
July 10, 2018
More Decks by shtnkgm
See All by shtnkgm
Combine入門
shtnkgm
2
320
Property Wrappers
shtnkgm
0
370
Saliency Detection
shtnkgm
0
86
パフォーマンス改善とユニットテスト
shtnkgm
4
1.7k
iOSのコードベースレイアウト
shtnkgm
2
840
20190117_iOSLT_CBLinSwift.pdf
shtnkgm
0
130
SwiftとFunctional Reactive Programming
shtnkgm
0
200
20180410_iOSLT_SwiftとProtocol-OrientedProgramming
shtnkgm
0
140
20180220_iOSLT_Swiftとオブジェクト間の通知のパターン
shtnkgm
0
170
Other Decks in Programming
See All in Programming
AI 輔助遺留系統現代化的經驗分享
jame2408
1
1.2k
1B+ /day規模のログを管理する技術
broadleaf
0
130
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
270
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
390
使用 Meilisearch 建立新聞搜尋工具
johnroyer
0
100
SREの積み重ねがAI駆動開発のガードレールになった ― 7つの実践/SRE Guardrails The 7
tomoyakitaura
7
2.9k
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
790
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
200
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
500
ローカルLLMでどこまでコードが書けるか -縮小版 / How much code can be written on a local LLM Shortened
kishida
2
180
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.9k
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
830
Featured
See All Featured
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
300
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
190
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
460
Scaling GitHub
holman
464
140k
Evolving SEO for Evolving Search Engines
ryanjones
0
240
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
480
Transcript
iOSͰDarkModeΛ࣮͢Δ 2018.7.10 iOSLT / Shota Nakagami (@shtnkgm)
Mojaveͷ৽ػೳDarkMode iOSͷαϙʔτͳ͍͚Ͳ࣮ͯ͠ΈΔ
DarkModeͬͯͲΜͳͷ?
None
None
DarkMode͔͍͍ͬ͜
DarkModeʹ͍͞͠
DarkMode
ࣗͰ࣮͢Δ
৭Λߟ͑Δ • ௨ৗ࣌ͱDarkModeͷ࣌ͲΜͳ৭ʹ͢Δ͔ • Human Interface GuidelinesʹMacOSͰͷDarkModeͷํ͋Γ • ͨͩ୯७ʹ໌Λస͢Εྑ͍Θ͚Ͱͳ͍ •
ݟ͍͢Α͏ʹDarkModeͰͷ৭ͷௐ͕ඞཁ • ۩ମతͳ৭ͷࢦఆGoogle Material Design͕ࢀߟʹͳΔ
৭ΛͱʹUIColorΛ֦ு͢Δ
UI DarkMode ௨ৗ ϝΠϯςΩετ ϗϫΠτʢα=100%ʣ ϒϥοΫʢα=87%ʣ αϒςΩετ ϗϫΠτʢα=70%ʣ ϒϥοΫʢα=54%ʣ DisabledςΩετ
ϗϫΠτʢα=50%ʣ ϒϥοΫʢα=38%ʣ ΞΫςΟϒΞΠίϯ ϗϫΠτʢα=100%ʣ ϒϥοΫʢα=54%ʣ ඇΞΫςΟϒΞΠίϯ ϗϫΠτʢα=38%ʣ ϒϥοΫʢα=50%ʣ σΟόΠμʔ άϨʔʢ#303030ʣ ϒϥοΫʢα=12%ʣ πʔϧόʔ άϨʔʢ#212121ʣ άϨʔʢ#F5F5F5ʣ Χʔυ άϨʔʢ#424242ʣ ϗϫΠτʢα=100%ʣ എܠ άϨʔʢ#303030ʣ άϨʔʢ#FAFAFAʣ
UIColorͷϓϥΠϕʔτExtensionͰෆಁ໌৭༻ͷมΛ࡞ private extension UIColor { static var gray050: UIColor {
return color("#FAFAFA") } static var gray100: UIColor { return color("#F5F5F5") } static var gray200: UIColor { return color("#EEEEEE") } static var gray300: UIColor { return color("#E0E0E0") } static var gray400: UIColor { return color("#BDBDBD") } static var gray500: UIColor { return color("#9E9E9E") } static var gray600: UIColor { return color("#757575") } static var gray700: UIColor { return color("#616161") } static var gray800: UIColor { return color("#424242") } static var gray850: UIColor { return color("#303030") } static var gray900: UIColor { return color("#212121") } }
UIColorͷϓϥΠϕʔτExtensionͰಁ໌৭༻ͷมΛ࡞ private extension UIColor { static var blackHalfTranslucent: UIColor {
return .init(white: 0, alpha: 0.5) } static var black012: UIColor { return .init(white: 1.00 - 0.12, alpha: 1) } static var black038: UIColor { return .init(white: 1.00 - 0.38, alpha: 1) } static var black050: UIColor { return .init(white: 1.00 - 0.50, alpha: 1) } static var black054: UIColor { return .init(white: 1.00 - 0.54, alpha: 1) } static var black070: UIColor { return .init(white: 1.00 - 0.70, alpha: 1) } static var black087: UIColor { return .init(white: 1.00 - 0.87, alpha: 1) } static var black100: UIColor { return .init(white: 1.00 - 1.00, alpha: 1) } static var whiteHalfTranslucent: UIColor { return .init(white: 1, alpha: 0.5) } static var white012: UIColor { return .init(white: 0.12, alpha: 1) } static var white038: UIColor { return .init(white: 0.38, alpha: 1) } static var white050: UIColor { return .init(white: 0.50, alpha: 1) } static var white054: UIColor { return .init(white: 0.54, alpha: 1) } static var white070: UIColor { return .init(white: 0.70, alpha: 1) } static var white087: UIColor { return .init(white: 0.87, alpha: 1) } static var white100: UIColor { return .init(white: 1.00, alpha: 1) } }
UIColorͷύϒϦοΫExtensionͰ෦৭ͷมΛ࡞ public extension UIColor { static var primary: UIColor {
return Config.shared.primaryColor } static var activeIcon: UIColor { return isDarkTheme ? .white100 : .black054 } static var inactiveIcon: UIColor { return isDarkTheme ? .white038 : .black050 } static var primaryText: UIColor { return isDarkTheme ? .white100 : .black087 } static var secondaryText: UIColor { return isDarkTheme ? .white070 : .black054 } static var disabledText: UIColor { return isDarkTheme ? .white050 : .black038 } static var linkText: UIColor { return .flatSkyBlue() } static var dividers: UIColor { return isDarkTheme ? .gray850 : .black012 } static var statusBar: UIColor { return isDarkTheme ? .black100 : .gray300 } static var appBar: UIColor { return isDarkTheme ? .gray900 : .gray100 } static var highlightedAppBar: UIColor { return isDarkTheme ? .gray800 : .gray200 } static var background: UIColor { return isDarkTheme ? .gray850 : .gray050 } static var card: UIColor { return isDarkTheme ? .gray800 : .white100 } static var highlightedCard: UIColor { return isDarkTheme ? .gray850 : .gray100 } }
৭Λࢦఆ͢Δ backgroundColor = .card mainLabel.textColor = .primaryText settingSwitch.onTintColor = .primary
ΞΠίϯը૾Ͳ͏͢Δʁ
UIImageΛUIColorͰృΕΔΑ͏ʹ͢Δ
public extension UIImage { public func image(withTint color: UIColor) ->
UIImage { let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) guard let context: CGContext = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return UIImage() } context.scaleBy(x: 1, y: -1) context.translateBy(x: 0, y: -self.size.height) context.clip(to: rect, mask: cgImage) context.setFillColor(color.cgColor) context.fill(rect) guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return UIImage() } UIGraphicsEndImageContext() return image } }
let iconImage = UIImage(named: "icon").image(withTint: .activeIcon)
image(withTint: )OSSͷta1n/Swi3ExtensionsͰར༻Մ
ࣗcontribu)onͯ͠·͢
ΊͰͨ͠ΊͰͨ͠
ΊͰͨ͠ΊͰͨ͠
ϞʔυΓସ͑࣌ʹ৭ͷมߋ͕ඞཁ DarkMode⁶௨ৗ
͜Ε͕Γ͍ͨ ΈΜͳʙ৭Λߋ৽ͯ͠ʙ
௨ઌ͕nݸͷ௨ͷΈͱ͍͑ʁ
No#fica#onCenter ࢀߟ: shtnkgm / Swi.ͱΦϒδΣΫτؒͷ௨ͷύλʔϯ
࣮֓ཁ 1. ֤ViewͰ௨Λߪಡ͓ͯ͘͠ 2. Ϟʔυͷมߋ࣌ʹNo*fica*onCenterͰ௨ 3. ֤ViewͰ௨Λड͚औΔ 4. ֤ViewͰ৭Λߋ৽
֤ViewͰड৴ॲཧΛॻ͘ͷ໘ public extension Notification.Name { static let styleUpdated = Notification.Name("styleUpdated")
} class HogeView { init() { let center = NotificationCenter.default center.addObserver(self, selector: #selector(updateStyle), name: .styleUpdated, object: nil) updateStyle() } @objc func updateStyle() { backgroundColor = .card } }
ϓϩτίϧͰॲཧΛڞ௨Խ
StyleUpdatable
public protocol StyleUpdatable: class { /// ௨Λղআ͢Δ߹ObserverΛอ࣋͢Δඞཁ͋Γ var updateStyleObserver: NSObjectProtocol?
{ get set } /// ৭ͷߋ৽ॲཧඞͣupdateStyleͱ͍͏໊લͷϝιουͰߦ͏ func updateStyle() }
public extension StyleUpdatable { /// updateStyleObserverΛҙ࣮ͱ͢ΔͨΊͷσϑΥϧτ࣮ var updateStyleObserver: NSObjectProtocol? {
get { return nil } set { } } /// ߪಡ & updateStyle()Λ࣮ߦ func observeAndUpdateStyle() { updateStyle() let center = NotificationCenter.default updateStyleObserver = center.addObserver(forName: .styleUpdated, object: nil, queue: nil) { [weak self] _ in self?.updateStyle() } } }
class HogeView: StyleUpdatable { init() { observeAndUpdateStyle() } // StyleUpdatableʹΑΓ࣮͕ڧ੍͞ΕΔ
func updateStyle() { backgroundColor = .card } }
ద༻αϯϓϧ ͡ͿΜͷΞϓϦͰಋೖ
None
None
None
None
ͦΕͬΆ͘ͳͬͨ
·ͱΊ • DarkModeͱ௨ৗ࣌ͷ৭Λߟ͑Δ • UIColorΛ֦ுͯ͠ɺDarkMode͔Ͳ͏͔Ͱذ (֤ViewDarkMode͔Ͳ͏͔Λߟྀ͠ͳͯ͘ྑ͍) • ΞΠίϯUIImageΛUIColorͰృΕΔΑ͏ʹ͢Δ • StyleUpdatableϓϩτίϧͰ৭ͷߋ৽ॲཧΛڞ௨Խ
͓ΘΓ ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠