* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


I read DarkMode recently. This article will explain statusBar (statusBar), UIActivityIndicatorView (activity indicator view), text drawing color and setting layer,border color, UIVisualEffectView when switching between bright/dark mode.

StatusBar

Developers planning to make DarkMode adaptations need to be aware of the type of statusBar they use.

  • Use UIStatusBarStyleLightContent type statusBar developers need to pay attention to Light mode, the status bar is unable to see the part of the content.

  • Want to use the next UIStatusBarStyleDarkContent type statusBar developers need to pay attention to the Dark mode, the status bar is unable to see the part of the content.

  • Except when we want our App or some interface to support only DarkMode or LightMode, we use a statusBar of type UIStatusBarStyleDefault.

The schematic diagram of different types of status bars in light and dark mode is as follows:

The sample code

- (UIStatusBarStyle)preferredStatusBarStyle {
    
    return UIStatusBarStyleDefault;
}
Copy the code

For more information about the status bar display style, you can check dac_1033’s notes on iOS status bar and navigation bar

UIActivityView

Using UIActivityIndicatorView UIActivityIndicatorViewStyleWhiteLarge developers need to pay attention to, UIActivityIndicatorViewStyleWhiteLarge style UIActivityIndicatorView cannot in basic invisible DarkMode mode. MBProgressHUD uses UIActivityIndicatorView, but because MBProgressHUD has a black container view nested on the outside, it works fine in Dark mode.

Recommend you use UIActivityIndicatorView UIActivityIndicatorViewStyleLarge or UIActivityIndicatorViewStyleMedium types.

Relevant schematic diagram is as follows, we can see only the middle UIActivityIndicatorViewStyleLarge types of UIActivityIndicatorView can again bright, dark mode can normal use, Of course, developers can also choose to change the tintColor of UIActivityIndicatorView to match DarkMode.

The sample code

    UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
Copy the code

Draw text colors and CGColors

Draw text color

If we use drawRect to draw an attribute string without specifying a color, the text color will default to black. Or maybe we set it to a darker color. In Dark mode, the corresponding text will be almost indistinct.

The schematic diagram is as follows:

In order for the drawn text to display properly when switching light/dark mode, we need to specify the color of the drawn text. Like explicitly setting

textAttris[NSForegroundColorAttributeName] = [UIColor labelColor];
Copy the code
Notice the string attribute dictionary nil Value

Because of the way string attribute dictionaries are specified, you may encounter one of the following problems when creating string attribute dictionaries.

Exception: * * * - [__NSPlaceholderDictionary initWithObjects: forKeys: count:] : attempt to insert nil object from objects [0]Copy the code

The above error is an exception for inserting nil into a dictionary. Note that [UIColor colorNamed:@”colorName”] is not null.

    if (@available(iOS 13.0, *)) {
        UIColor *forgroundColor = [UIColor colorNamed:@"colorName"];
        if (forgroundColor) {
            NSAttributedString *attriString = [[NSAttributedString alloc] initWithString:@"QiShare" attributes:@{NSForegroundColorAttributeName: forgroundColor}];
            NSLog(@ property string %@, attriString); }}Copy the code

CGColor

Use parts to CGColor, such as Layer color, border color. When setting the Layer color, it will be found that it cannot be switched smoothly during the switching of bright and dark modes. The color can be set at an appropriate time. In the author’s opinion, the corresponding color can be set once more during traitCollectionDidChange to avoid the phenomenon of not smooth switching.

The relevant schematic diagram is as follows.

For the two views in the screenshot, the upper view cannot be switched with the light/dark mode. The view below can be switched with light/dark mode.

Related implementation can in – (void) traitCollectionDidChange previousTraitCollection in operation: (UITraitCollection *).

Sample code:

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    
    if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
        self.normalColorLayer.backgroundColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
            if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
                return [UIColor redColor];
            } else {
                return [UIColor blueColor];
            }
        }].CGColor;
        self.normalColorLayer.borderColor = [UIColorsystemBackgroundColor].CGColor; }}Copy the code

UIVisualEffectView

About UIVisualEffectView, I know little about it. Xs·H also mentioned the related scene and the fuzzy mask when the application goes back to the background. According to the official Demo and documents made the following effect of the diagram, you can download QiDarkMode to view the relevant code implementation.

Description of official documents: Visual-effect views add transparency to your background views, which gives your UI more visual depth than if the backgrounds were opaque. To ensure that your content remains visible, visual-effect views blur the background content subtly and add vibrancy effects to adjust the colors of your foreground content automatically. The system updates these effects dynamically, ensuring that your app’s content remains visible when the underlying content changes.

Sample code:

   / / create UIVisualEffectView
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemThinMaterial];
    UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    visualEffectView.frame = CGRectMake(. 0.100.0.CGRectGetWidth(self.view.frame), 150.0);
    [self.view addSubview:visualEffectView];
    
    / / create UIVibrancyEffect
    UIVibrancyEffect *vibrancyEffect =
    [UIVibrancyEffect effectForBlurEffect:blurEffect style:UIVibrancyEffectStyleSecondaryLabel];
    UIVisualEffectView *vibrancyView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
    [visualEffectView.contentView addSubview:vibrancyView];
    vibrancyView.frame = visualEffectView.bounds;
    vibrancyView.frame = CGRectMake(. 0.. 0.CGRectGetWidth(visualEffectView.frame), CGRectGetHeight(visualEffectView.frame) * 0.5);
    
    UILabel *label = [UILabel new];
    label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleLargeTitle compatibleWithTraitCollection:self.traitCollection];
    label.text = @"Vibrant Label1";
    [vibrancyView.contentView addSubview:label];
    label.frame = vibrancyView.bounds;
Copy the code

other

Fixed setting of App or some interface light/dark mode

  • Fixed setting App light/dark mode

Fixed Light mode: Set User Interface Style to “Light” in the info.plist file

Fixed Dark mode: set User Interface Style to “Dark” in the info.plist file

  • Fixed some pages to light/dark mode

Method: the corresponding controller rewrite overrideUserInterfaceStyle.

Fixed light mode:

- (UIUserInterfaceStyle)overrideUserInterfaceStyle {

    return UIUserInterfaceStyleLight;
}
Copy the code

Fixed dark mode:

- (UIUserInterfaceStyle)overrideUserInterfaceStyle {

    return UIUserInterfaceStyleDark;
}
Copy the code

Demo

See Demo: QiDarkMode for details

Refer to study website

  • Developer.apple.com/documentati…
  • Developer.apple.com/library/arc…
  • www.fivestars.blog/code/ios-da…
  • Webkit.org/blog/8840/d…

Recommended articles:

Swift 5.1 (3) – String Write a simple page with Flutter for 5 minutes, Markdown Grammar Swift 5.1(2) – Operator Swift 5.1(1) – Basics Sign In With Apple (a) Weird Dance weekly