20180710_iOSLT_iOSでDarkModeを実装する

 20180710_iOSLT_iOSでDarkModeを実装する

E45f9c343d90c74554c65c89c6f861bc?s=128

shtnkgm

July 10, 2018
Tweet

Transcript

  1. iOSͰDarkModeΛ࣮૷͢Δ 2018.7.10 iOSLT / Shota Nakagami (@shtnkgm)

  2. Mojaveͷ৽ػೳDarkMode iOSͷαϙʔτ͸ͳ͍͚Ͳ࣮૷ͯ͠ΈΔ࿩

  3. DarkModeͬͯͲΜͳͷ?

  4. None
  5. None
  6. DarkMode͔͍͍ͬ͜

  7. DarkMode͸໨ʹ΍͍͞͠

  8. DarkMode

  9. ࣗ෼Ͱ࣮૷͢Δ

  10. ഑৭Λߟ͑Δ • ௨ৗ࣌ͱDarkModeͷ࣌ͲΜͳ৭ʹ͢Δ͔ • Human Interface GuidelinesʹMacOSͰͷDarkModeͷํ਑͋Γ • ͨͩ୯७ʹ໌౓Λ൓స͢Ε͹ྑ͍Θ͚Ͱ͸ͳ͍ •

    ݟ΍͍͢Α͏ʹDarkModeͰͷ৭ͷௐ੔͕ඞཁ • ۩ମతͳ৭ͷࢦఆ஋͸Google Material Design͕ࢀߟʹͳΔ
  11. ഑৭Λ΋ͱʹUIColorΛ֦ு͢Δ

  12. UI DarkMode ௨ৗ ϝΠϯςΩετ ϗϫΠτʢα=100%ʣ ϒϥοΫʢα=87%ʣ αϒςΩετ ϗϫΠτʢα=70%ʣ ϒϥοΫʢα=54%ʣ DisabledςΩετ

    ϗϫΠτʢα=50%ʣ ϒϥοΫʢα=38%ʣ ΞΫςΟϒΞΠίϯ ϗϫΠτʢα=100%ʣ ϒϥοΫʢα=54%ʣ ඇΞΫςΟϒΞΠίϯ ϗϫΠτʢα=38%ʣ ϒϥοΫʢα=50%ʣ σΟόΠμʔ άϨʔʢ#303030ʣ ϒϥοΫʢα=12%ʣ πʔϧόʔ άϨʔʢ#212121ʣ άϨʔʢ#F5F5F5ʣ Χʔυ άϨʔʢ#424242ʣ ϗϫΠτʢα=100%ʣ എܠ άϨʔʢ#303030ʣ άϨʔʢ#FAFAFAʣ
  13. 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") } }
  14. 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) } }
  15. 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 } }
  16. ৭Λࢦఆ͢Δ backgroundColor = .card mainLabel.textColor = .primaryText settingSwitch.onTintColor = .primary

  17. ΞΠίϯը૾͸Ͳ͏͢Δʁ

  18. UIImageΛUIColorͰృΕΔΑ͏ʹ͢Δ

  19. 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 } }
  20. let iconImage = UIImage(named: "icon").image(withTint: .activeIcon)

  21. image(withTint: )͸OSSͷta1n/Swi3ExtensionsͰར༻Մ

  22. ࣗ෼΋contribu)onͯ͠·͢

  23. ΊͰͨ͠ΊͰͨ͠

  24. ΊͰͨ͠ΊͰͨ͠

  25. Ϟʔυ੾Γସ͑࣌ʹ৭ͷมߋ͕ඞཁ DarkMode⁶௨ৗ

  26. ͜Ε͕΍Γ͍ͨ ΈΜͳʙ৭Λߋ৽ͯ͠ʙ

  27. ௨஌ઌ͕nݸͷ௨஌ͷ࢓૊Έͱ͍͑͹ʁ

  28. No#fica#onCenter ࢀߟ: shtnkgm / Swi.ͱΦϒδΣΫτؒͷ௨஌ͷύλʔϯ

  29. ࣮૷֓ཁ 1. ֤ViewͰ௨஌Λߪಡ͓ͯ͘͠ 2. Ϟʔυͷมߋ࣌ʹNo*fica*onCenterͰ௨஌ 3. ֤ViewͰ௨஌Λड͚औΔ 4. ֤ViewͰ৭Λߋ৽

  30. ֤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 } }
  31. ϓϩτίϧͰॲཧΛڞ௨Խ

  32. StyleUpdatable

  33. public protocol StyleUpdatable: class { /// ௨஌Λղআ͢Δ৔߹͸ObserverΛอ࣋͢Δඞཁ͋Γ var updateStyleObserver: NSObjectProtocol?

    { get set } /// ৭ͷߋ৽ॲཧ͸ඞͣupdateStyleͱ͍͏໊લͷϝιουͰߦ͏ func updateStyle() }
  34. 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() } } }
  35. class HogeView: StyleUpdatable { init() { observeAndUpdateStyle() } // StyleUpdatableʹΑΓ࣮૷͕ڧ੍͞ΕΔ

    func updateStyle() { backgroundColor = .card } }
  36. ద༻αϯϓϧ ͡ͿΜͷΞϓϦͰಋೖ

  37. None
  38. None
  39. None
  40. None
  41. ͦΕͬΆ͘ͳͬͨ

  42. ·ͱΊ • DarkModeͱ௨ৗ࣌ͷ഑৭Λߟ͑Δ • UIColorΛ֦ுͯ͠ɺDarkMode͔Ͳ͏͔Ͱ෼ذ (֤View͸DarkMode͔Ͳ͏͔Λߟྀ͠ͳͯ͘ྑ͍) • ΞΠίϯ͸UIImageΛUIColorͰృΕΔΑ͏ʹ͢Δ • StyleUpdatableϓϩτίϧͰ৭ͷߋ৽ॲཧΛڞ௨Խ

  43. ͓ΘΓ ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠