Upgrade to Pro — share decks privately, control downloads, hide ads and more …

20180710_iOSLT_iOSでDarkModeを実装する

 20180710_iOSLT_iOSでDarkModeを実装する

shtnkgm

July 10, 2018
Tweet

More Decks by shtnkgm

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. DarkModeͬͯͲΜͳͷ?

    View Slide

  4. View Slide

  5. View Slide

  6. DarkMode͔͍͍ͬ͜

    View Slide

  7. DarkMode͸໨ʹ΍͍͞͠

    View Slide

  8. DarkMode

    View Slide

  9. ࣗ෼Ͱ࣮૷͢Δ

    View Slide

  10. ഑৭Λߟ͑Δ
    • ௨ৗ࣌ͱDarkModeͷ࣌ͲΜͳ৭ʹ͢Δ͔
    • Human Interface GuidelinesʹMacOSͰͷDarkModeͷํ਑͋Γ
    • ͨͩ୯७ʹ໌౓Λ൓స͢Ε͹ྑ͍Θ͚Ͱ͸ͳ͍
    • ݟ΍͍͢Α͏ʹDarkModeͰͷ৭ͷௐ੔͕ඞཁ
    • ۩ମతͳ৭ͷࢦఆ஋͸Google Material Design͕ࢀߟʹͳΔ

    View Slide

  11. ഑৭Λ΋ͱʹUIColorΛ֦ு͢Δ

    View Slide

  12. UI DarkMode ௨ৗ
    ϝΠϯςΩετ ϗϫΠτʢα=100%ʣ ϒϥοΫʢα=87%ʣ
    αϒςΩετ ϗϫΠτʢα=70%ʣ ϒϥοΫʢα=54%ʣ
    DisabledςΩετ ϗϫΠτʢα=50%ʣ ϒϥοΫʢα=38%ʣ
    ΞΫςΟϒΞΠίϯ ϗϫΠτʢα=100%ʣ ϒϥοΫʢα=54%ʣ
    ඇΞΫςΟϒΞΠίϯ ϗϫΠτʢα=38%ʣ ϒϥοΫʢα=50%ʣ
    σΟόΠμʔ άϨʔʢ#303030ʣ ϒϥοΫʢα=12%ʣ
    πʔϧόʔ άϨʔʢ#212121ʣ άϨʔʢ#F5F5F5ʣ
    Χʔυ άϨʔʢ#424242ʣ ϗϫΠτʢα=100%ʣ
    എܠ άϨʔʢ#303030ʣ άϨʔʢ#FAFAFAʣ

    View Slide

  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") }
    }

    View Slide

  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) }
    }

    View Slide

  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 }
    }

    View Slide

  16. ৭Λࢦఆ͢Δ
    backgroundColor = .card
    mainLabel.textColor = .primaryText
    settingSwitch.onTintColor = .primary

    View Slide

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

    View Slide

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

    View Slide

  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
    }
    }

    View Slide

  20. let iconImage = UIImage(named: "icon").image(withTint: .activeIcon)

    View Slide

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

    View Slide

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

    View Slide

  23. ΊͰͨ͠ΊͰͨ͠

    View Slide

  24. ΊͰͨ͠ΊͰͨ͠

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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
    }
    }

    View Slide

  31. ϓϩτίϧͰॲཧΛڞ௨Խ

    View Slide

  32. StyleUpdatable

    View Slide

  33. public protocol StyleUpdatable: class {
    /// ௨஌Λղআ͢Δ৔߹͸ObserverΛอ࣋͢Δඞཁ͋Γ
    var updateStyleObserver: NSObjectProtocol? { get set }
    /// ৭ͷߋ৽ॲཧ͸ඞͣupdateStyleͱ͍͏໊લͷϝιουͰߦ͏
    func updateStyle()
    }

    View Slide

  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()
    }
    }
    }

    View Slide

  35. class HogeView: StyleUpdatable {
    init() {
    observeAndUpdateStyle()
    }
    // StyleUpdatableʹΑΓ࣮૷͕ڧ੍͞ΕΔ
    func updateStyle() {
    backgroundColor = .card
    }
    }

    View Slide

  36. ద༻αϯϓϧ
    ͡ͿΜͷΞϓϦͰಋೖ

    View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. View Slide

  41. ͦΕͬΆ͘ͳͬͨ

    View Slide

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

    View Slide

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

    View Slide