Tambahkan tema gelap di iOS

Halo semuanya!

Nama saya Andrey, saya dari tim Broker Saya. Saya akan memberi tahu Anda ĸĸ menambahkan dukungan untuk tema gelap di iOS.

Apple di iOS 13 menambahkan tema gelap untuk seluruh sistem, pengguna dapat memilih tampilan terang atau gelap pada pengaturan iOS. Dalam mode gelap, sistem menggunakan palet warna yang lebih gelap untuk semua layar, tampilan, menu, dan kontrol.

gambar

Siapa yang peduli - pergi di bawah kucing.

Dukungan desain gelap


Aplikasi yang dibuat di Xcode 11 secara default mendukung desain gelap di iOS 13. Tetapi untuk implementasi penuh dari mode gelap, Anda perlu melakukan perubahan tambahan:

  • Warna harus mendukung desain terang dan gelap
  • Gambar harus mendukung desain terang dan gelap

Apple telah menambahkan beberapa warna sistem yang mendukung desain terang dan gelap.
gambar

Di iOS 13, penginisialisasi UIColor baru diperkenalkan :

init (dynamicProvider: @escaping (UITraitCollection) -> UIColor)

Tambahkan fungsi statis untuk membuat warna dengan dukungan untuk beralih antara desain terang dan gelap:

extension UIColor {
    
    static func color(light: UIColor, dark: UIColor) -> UIColor {
        if #available(iOS 13, *) {
            return UIColor.init { traitCollection in
                return traitCollection.userInterfaceStyle == .dark ? dark : light
            }
        } else {
            return light
        }
    }
}

CGColor tidak mendukung peralihan otomatis antara terang dan gelap. Anda harus mengubah CGColor secara manual setelah mengubah desain.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
        
    layer.borderColor = UIColor.Pallete.black.cgColor
}

Dimungkinkan juga untuk menambahkan warna untuk dekorasi gelap di sumber daya.

gambar

Tapi saya lebih suka menambahkan warna dalam kode.

UIColor. Palet
extension UIColor {
    
    struct Pallete {

        static let white = UIColor.color(light: .white, dark: .black)
        static let black = UIColor.color(light: .black, dark: .white)

        static let background = UIColor.color(light: .white, dark: .hex("1b1b1d"))
        static let secondaryBackground = UIColor(named: "secondaryBackground") ?? .black

        static let gray = UIColor.color(light: .lightGray, dark: .hex("8e8e92"))

    }
}


Untuk gambar, cukup tambahkan varian gambar untuk desain gelap tepat di sumber daya.

gambar

Mari kita membuat aplikasi kecil sebagai contoh.


Aplikasi akan berisi dua jendela dan tiga layar.

Jendela pertama: layar otorisasi.

Jendela kedua: layar pita dan layar profil pengguna.

Screenshot dalam desain terang dan gelap
gambar gambar gambar
gambar gambar gambar

Ganti tema terang dan gelap


Buat enum untuk topik:


enum Theme: Int, CaseIterable {
    case light = 0
    case dark
}

Kami menambahkan kemampuan untuk menyimpan tema saat ini untuk mengembalikannya setelah memulai ulang aplikasi.

extension Theme {
    
    //   UserDefaults
    @Persist(key: "app_theme", defaultValue: Theme.light.rawValue)
    private static var appTheme: Int
    
    //    UserDefaults
    func save() {
        Theme.appTheme = self.rawValue
    }
    
    //   
    static var current: Theme {
        Theme(rawValue: appTheme) ?? .light
    }
}

Bertahan
@propertyWrapper
struct Persist<T> {
    let key: String
    let defaultValue: T
    
    var wrappedValue: T {
        get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
        set { UserDefaults.standard.set(newValue, forKey: key) }
    }
    
    init(key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }
}


Untuk memaksakan desain, Anda perlu mengubah gaya semua jendela aplikasi.

Kami menerapkan pengalihan tema dalam aplikasi.


extension Theme {
    
    @available(iOS 13.0, *)
    var userInterfaceStyle: UIUserInterfaceStyle {
        switch self {
        case .light: return .light
        case .dark: return .dark
        }
    }
    
    func setActive() {
        //   
        save()
        
        guard #available(iOS 13.0, *) else { return }
        
        //       
        UIApplication.shared.windows
            .forEach { $0.overrideUserInterfaceStyle = userInterfaceStyle }
    }
}

Anda juga perlu mengubah gaya jendela ke tema saat ini sebelum menampilkan jendela.

extension UIWindow {
    
    //     
    //     
    func initTheme() {
        guard #available(iOS 13.0, *) else { return }
        
        overrideUserInterfaceStyle = Theme.current.userInterfaceStyle
    }
}

Cuplikan layar memilih tema terang atau gelap
gambar gambar

Tambahkan peralihan ke tema sistem


Tambahkan tema sistem ke tema enum.
enum Theme: Int, CaseIterable {
    case system = 0
    case light
    case dark
}

Setelah pemasangan paksa tema terang atau gelap, tidak mungkin untuk menentukan desain mana yang termasuk dalam sistem. Untuk mengenali desain sistem, kami menambahkan jendela ke aplikasi, di mana kami tidak akan memaksakan perubahan desain. Anda juga perlu menerapkan perubahan desain saat aplikasi memiliki tema sistem yang diinstal dan pengguna mengubah desain di iOS.

final class ThemeWindow: UIWindow {
    
    override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

        //         iOS,     .
        // :      .
        if Theme.current == .system {
            Theme.system.setActive()
        }
    }
}

let themeWindow = ThemeWindow()

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ...
        //    ,    
        //       
        themeWindow.makeKey()
        ...
        return true
    }
}

extension Theme {
    
    @available(iOS 13.0, *)
    var userInterfaceStyle: UIUserInterfaceStyle {
        switch self {
        case .light: return .light
        case .dark: return .dark
        case .system: return themeWindow.traitCollection.userInterfaceStyle
        }
    }
    
    func setActive() {
        //   
        save()
        
        guard #available(iOS 13.0, *) else { return }
        
        //       
        //        
        UIApplication.shared.windows
            .filter { $0 != themeWindow } 
            .forEach { $0.overrideUserInterfaceStyle = userInterfaceStyle }
    }
}

Cuplikan layar memilih sistem, tema terang atau gelap
gambar gambar

Hasil


Dukungan untuk desain gelap dan beralih antara sistem, tema terang dan gelap.
Layar video


Tautan ke seluruh proyek

All Articles