أضف سمة داكنة في iOS

تحية للجميع!

اسمي أندري ، أنا من فريق My Broker. سأخبرك بأنه تمت إضافة دعم لمظهر مظلم في iOS.

أضافت Apple في iOS 13 مظهرًا داكنًا للنظام بأكمله ، يمكن للمستخدمين اختيار مظهر فاتح أو غامق على إعدادات iOS. في الوضع الداكن ، يستخدم النظام لوحة ألوان أكثر قتامة لجميع الشاشات وطرق العرض والقوائم وعناصر التحكم.

صورة

من يهتم - اذهب تحت القطة.

دعم التصميم الداكن


التطبيق الذي تم إنشاؤه في Xcode 11 بشكل افتراضي يدعم التصميم الداكن في iOS 13. ولكن من أجل التنفيذ الكامل للوضع المظلم ، تحتاج إلى إجراء تغييرات إضافية:

  • يجب أن تدعم الألوان التصميم الفاتح والداكن
  • يجب أن تدعم الصور التصميم الفاتح والداكن

أضافت Apple العديد من ألوان النظام التي تدعم التصميم الفاتح والداكن.
صورة

في iOS 13 ، تم تقديم مُهيئ UIColor الجديد :

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

أضف وظيفة ثابتة لإنشاء اللون مع دعم التبديل بين التصميم الفاتح والداكن:

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 التبديل التلقائي بين الضوء والظلام. يجب تغيير CGColor يدويًا بعد تغيير التصميم.

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

من الممكن أيضًا إضافة لون للزخرفة الداكنة في الموارد.

صورة

لكنني أفضل إضافة الألوان في الكود.

UIColor.Pallete
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"))

    }
}


للصور ، ما عليك سوى إضافة متغير من الصورة لتصميم داكن في الموارد.

صورة

دعونا نجعل تطبيقًا صغيرًا كمثال.


سيحتوي التطبيق على نافذتين وثلاث شاشات.

النافذة الأولى: شاشة الترخيص.

النافذة الثانية: شاشة الشريط وشاشة ملف تعريف المستخدم.

لقطات شاشة في الضوء والظلام
صورة صورة صورة
صورة صورة صورة

قم بتغيير السمات الفاتحة والداكنة


إنشاء تعداد للموضوع:


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

نضيف القدرة على تخزين السمة الحالية لاستعادتها بعد إعادة تشغيل التطبيق.

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

ثابر
@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
    }
}


لفرض التصميم ، تحتاج إلى تغيير نمط جميع نوافذ التطبيق.

نقوم بتنفيذ تبديل السمات في التطبيق.


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

من الضروري أيضًا تغيير نمط النافذة إلى السمة الحالية قبل إظهار النافذة.

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

لقطات شاشة لاختيار مظهر فاتح أو غامق
صورة صورة

أضف مفتاحًا لموضوع النظام


قم بإضافة سمة نظام إلى سمة التعداد.
enum Theme: Int, CaseIterable {
    case system = 0
    case light
    case dark
}

بعد التثبيت القسري للسمة الفاتحة أو الداكنة ، من المستحيل تحديد التصميم المتضمن في النظام. للتعرف على تصميم النظام ، نضيف نافذة إلى التطبيق ، حيث لن نفرض تغيير التصميم. من الضروري أيضًا إجراء تغيير في التصميم عندما يكون التطبيق يحتوي على سمة نظام مثبتة ويغير المستخدم التصميم في 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 }
    }
}

لقطات شاشة لاختيار نظام أو مظهر فاتح أو غامق
صورة صورة

نتيجة


دعم التصميم الداكن والتبديل بين سمات النظام والضوء والظلام.
شاشة فيديو


رابط للمشروع بأكمله

All Articles