iOS 14 Widget Detect System Theme Change

iOS 14 Widget Detect System Theme Change

Although Widget views are static, you may still detect @Environment(\.colorScheme).

Here is a simple demo:

struct WidgetEntryView: View {
@Environment(\.colorScheme) var colorScheme

var entry: Provider.Entry

var bgColor: some View {
colorScheme == .dark ? Color.red : Color.orange
}

var body: some View {
ZStack {
bgColor
Text(entry.date, style: .time)
}
}
}

Note that when the system color scheme changes:

  • only your View is redrawn, the getTimeline function is not called again
  • the default colors change automatically when the system color scheme changes

Here is a GitHub repository with different Widget examples including the Environment Widget.

Update Widget when appearance changes

  1. Create two screenshots (one per theme) and pass it in the entry:
struct SimpleEntry: TimelineEntry {
let date: Date
let mapScreenshots: [ColorScheme: Image]
}
struct Provider: TimelineProvider {
...

func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let entry = SimpleEntry(
date: Date(),
mapScreenshots: [
// replace with actual map screenshots
.dark: Image(systemName: "plus"),
.light: Image(systemName: "minus"),
]
)
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
}

  1. Use @Environment(\.colorScheme) to react to theme changes:
struct WidgetEntryView: View {
@Environment(\.colorScheme) var colorScheme

var entry: Provider.Entry

var body: some View {
if let screenshot = entry.mapScreenshots[colorScheme] {
screenshot
}
}
}
  • iOS 14 Widget Detect System Theme Change

Disable Light Mode in Widget Extension iOS 14

Add the desired color to the widget’s asset catalog, then set the NSWidgetBackgroundColorName in your widget’s build settings.

Docs:
https://developer.apple.com/documentation/bundleresources/information_property_list/nswidgetbackgroundcolorname

Changing iOS App theme automatically between light and dark depending on iOS environmental theme

After banging my head against a brick wall for a few hours, finally figured it out (For anyone else having a similar issue).

The trick is that yes, you do in fact need to place the code that selects the theme inside the line

return CupertinoApp( <Here> )

You can do this through:

builder: (BuildContext context, Widget child) {

final Brightness brightnessValue = MediaQuery.of(context).platformBrightness;
bool isDark = brightnessValue == Brightness.dark;

// All your code to set your two themes, light and dark can go here.

}

In this way, instead of the chicken&egg scenario I was imagining, you are setting the theme state at the moment you need it.

Hope this helps someone.

How to check if dark mode is enabled on iOS/Android using Flutter?

There are two ways:

  1. NO context required. Can be used in initState for example:

     var brightness = SchedulerBinding.instance.window.platformBrightness;
    bool isDarkMode = brightness == Brightness.dark;

    or (as suggested by Moore's Lawyer)

     var brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness;
    bool isDarkMode = brightness == Brightness.dark;
  2. context is required:

     var brightness = MediaQuery.of(context).platformBrightness;
    bool isDarkMode = brightness == Brightness.dark;

iOS 14 Widget auto-refresh every day

Actually, it seems to be I overlooked it, the widget actually refreshes, it was me, who didn't refresh the data itself. (I'm using UserDefaults to share data between my app and the widget, and even though the widget refreshed properly, as the data in UserDefaults was not updated, the same was shown over and over again.)

How can I check whether dark mode is enabled in iOS/iPadOS?

SwiftUI

With the \.colorScheme key of an Environment variable:

struct ContentView: View {
@Environment(\.colorScheme) var colorScheme

var body: some View {
Text(colorScheme == .dark ? "In dark mode" : "In light mode")
}
}

Also, it automatically updates on the change of the environment color scheme.



UIKit

To check the current, all object those conform to UITraitEnvironment protocol, including all UIView subclasses and all UIViewConttroller subclasses have access to the current style:

myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark

To detect live changes of the style, here is the full detailed answer



Related Topics



Leave a reply



Submit