如何在应用程序中使用自定义颜色轻松支持明暗模式? [英] How do I easily support light and dark mode with a custom color used in my app?

查看:142
本文介绍了如何在应用程序中使用自定义颜色轻松支持明暗模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我的应用程序中有自定义颜色:

Let's say I have a custom color in my app:

extension UIColor {
    static var myControlBackground: UIColor {
        return UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 1)
    }
}

我在自定义控件(和其他地方)中使用它作为控件的背景:

I use this in a custom control (and other places) as the control's background:

class MyControl: UIControl {
    override init(frame: CGRect) {
        super.init(frame: frame)

        setup()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)

        setup()
    }

    private func setup() {
        backgroundColor = .myControlBackground
    }

    // Lots of code irrelevant to the question
}

在iOS 13上,我希望自定义控件同时支持亮模式和暗模式.

With iOS 13, I wish to have my custom control support both light and dark mode.

一种解决方案是覆盖traitCollectionDidChange并查看颜色是否已更改,然后根据需要更新我的背景.我还需要提供浅色和深色.

One solution is to override traitCollectionDidChange and see if the color has changed and then update my background as needed. I also need to provide both a light and dark color.

所以我更新了自定义颜色:

So I update my custom colors:

extension UIColor {
    static var myControlBackgroundLight: UIColor {
        return UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 1)
    }
    static var myControlBackgroundDark: UIColor {
        return UIColor(red: 0.4, green: 0.3, blue: 0.2, alpha: 1)
    }
}

然后我更新我的控制代码:

And I update my control code:

extension MyControl {
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if #available(iOS 13.0, *) {
            if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
                backgroundColor = traitCollection.userInterfaceStyle == .dark ?
                   .myControlBackgroundDark : .myControlBackgroundLight
            }
        }
    }
}

这似乎可行,但是笨拙,我碰巧在其他任何地方使用myControlBackground都需要添加相同的代码.

This seems to work but it's clunky and anywhere else I happen to use myControlBackground needs to have the same code added.

让我的自定义颜色和控件同时支持亮模式和暗模式是否有更好的解决方案?

Is there a better solution to having my custom color and control support both light and dark mode?

推荐答案

事实证明,使用新的UIColor init(dynamicProvider:)初始化器确实很容易.

As it turns out, this is really easy with the new UIColor init(dynamicProvider:) initializer.

将自定义颜色更新为:

extension UIColor {
    static var myControlBackground: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor { (traits) -> UIColor in
                // Return one of two colors depending on light or dark mode
                return traits.userInterfaceStyle == .dark ?
                    UIColor(red: 0.5, green: 0.4, blue: 0.3, alpha: 1) :
                    UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 1)
            }
        } else {
            // Same old color used for iOS 12 and earlier
            return UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 1)
        }
    }
}

就是这样.无需定义两个单独的静态变量.控件类不需要对原始代码进行任何更改.无需覆盖traitCollectionDidChange或其他任何内容.

That's it. No need to define two separate statics. The control class doesn't need any changes from the original code. No need to override traitCollectionDidChange or anything else.

有趣的是,在设置"应用程序中更改模式后,您可以立即在应用程序切换器中看到颜色更改.当然,当您返回应用程序时,颜色会自动更新.

The nice thing about this is that you can see the color change in the app switcher immediately after changing the mode in the Settings app. And of course the color is up-to-date automatically when you go back to the app.

在支持明暗模式时的相关说明上-尽可能使用UIColor提供的多种颜色.查看 UI元素

On a related note when supporting light and dark mode - Use as many of the provided colors from UIColor as possible. See the available dynamic colors from UI Elements and Standard Colors. And when you need your own app-specific colors to support both light and dark mode, use the code in this answer as an example.

在Objective-C中,您可以使用以下方法定义自己的动态颜色:

In Objective-C, you can define your own dynamic colors with:

UIColor + MyApp.h:

UIColor+MyApp.h:

@interface UIColor (MyApp)

@property (class, nonatomic, readonly) UIColor *myControlBackgroundColor;

@end

UIColor + MyApp.m:

UIColor+MyApp.m:

+ (UIColor *)myControlBackgroundColor {
    if (@available(iOS 13.0, *)) {
        return [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traits) {
            return traits.userInterfaceStyle == UIUserInterfaceStyleDark ?
                [self colorWithRed:0.5 green:0.4 blue:0.2 alpha:1.0] :
                [self colorWithRed:0.3 green:0.4 blue:0.5 alpha:1.0];
        }];
    } else {
        return [self colorWithRed:0.3 green:0.4 blue:0.5 alpha:1.0];
    }
}

这篇关于如何在应用程序中使用自定义颜色轻松支持明暗模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆