0

When switching the application to dark mode, the confirmationDialog is displayed in white. How can I make the confirmationDialog also show up in dark mode?

import SwiftUI

struct SettingListView: View, Themeable {
    @Environment(\.dismiss) var dismiss
    @State private var showingConfirmation = false
    @Environment(\.colorScheme) var colorScheme
    @AppStorage("isDarkMode") private var isDarkMode = false
    @StateObject var settingsListViewModel = SettingsListViewModel()
    @State private var changeValueID = true
    @State private var showContacts = true
    
    var body: some View {
        NavigationStack {
            List {
                Section {
                    VStack {
                        ZStack(alignment: .bottomTrailing) {
                            Image("avatar")
                                .resizable()
                                .scaledToFill()
                                .frame(width: 120, height: 120)
                                .clipShape(Circle())
                                .onTapGesture {
                                    showingConfirmation = true
                                }
                                .confirmationDialog("Change Profile Picture", isPresented: $showingConfirmation, titleVisibility: .visible) {
                                    Button(role: .none, action: {}) {
                                        Text("Take Photo")
                                    }
                                    Button(role: .none, action: {}) {
                                        Text("Choose from library")
                                    }
                                    Button(role: .none, action: {}) {
                                        Text("Use Avatar")
                                    }
                                }
                            Image(systemName: "pencil")
                                .foregroundColor(isDarkMode ? .white : .black)
                                .frame(width: 28, height: 28)
                                .background(isDarkMode ? Color(#colorLiteral(red: 0.370555222, green: 0.3705646992, blue: 0.3705595732, alpha: 1)) : Color(#colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1)))
                                .clipShape(Circle())
                                .overlay {
                                    Circle().stroke(isDarkMode ? .black : Color(.secondarySystemBackground), lineWidth: 4)
                                }
                                .scaleEffect(x: 1.1, y: 1.1, anchor: .center)
                        }
                    }

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
  • Please see [ask] including the section on using text for code (not images). You'd also want to include a [mre]. – jnpdx Jul 19 '23 at 14:58
  • Did you try just to omit the background color definition and let the OS use the default value? – J Kasparian Jul 19 '23 at 15:07
  • Haven't tried. In Assets, I set the colors for the light and dark theme and thought that it would change colors everywhere. – Visal Kazymov Jul 19 '23 at 15:22
  • Does this answer your question? [Change background color when dark mode turns on in SwiftUI](https://stackoverflow.com/questions/59694589/change-background-color-when-dark-mode-turns-on-in-swiftui) – HangarRash Jul 19 '23 at 17:09
  • Unfortunately no. I think only making a custom confirmationDialog will help here. – Visal Kazymov Jul 20 '23 at 07:40

3 Answers3

0

You may want to to add the .preferredColorScheme()

@State private var isDarkMode = false
  Image(Avatar)
   .confirmationDialog(.....) {
    VStack {
      ....
    }
    .preferredColorScheme(isDarkMode ? .dark : .light)
   }
   

Something like that. May need to play with where the modifier is. I've never used it so Im not entirely sure where it would go.

JerryC
  • 3
  • 3
0
if colorScheme == .dark {

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .white

} else {

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .black

}

This works but it would make your entire .confirmationDialog of the same color.

devdchaudhary
  • 467
  • 2
  • 13
  • When adding code, it gives an error "Type '()' cannot conform to 'View'". I'm new to this site and I don't know how to add code to the answer. Maybe I'm doing something wrong. I'm just still a beginner. – Visal Kazymov Jul 19 '23 at 19:05
  • add this inside an ```.onappear``` closure on your view. – devdchaudhary Jul 20 '23 at 12:18
  • @ lemonator21 Thanks, this helped. Only now the confirmationDialog appears differently, namely: all the buttons are located in one block. Prior to this, by default, the cancel button is at a small distance from other buttons. Also now the window appears without rounded corners. – Visal Kazymov Jul 20 '23 at 16:08
  • What do you mean one block? The only thing this changes is the color of all UIAlerts across your app. – devdchaudhary Jul 20 '23 at 17:53
  • It's possible to override SwiftUI functionality using UIKit. – devdchaudhary Jul 20 '23 at 22:12
  • @lemonator21 In addition to color, it has also changed in appearance. I have three buttons in my code: "Change Profile Picture", "Choose from library", Use Avatar". They are located one after another. The "Cancel" button is located at a short distance from them. At the same time, the corners of the pop-up window are rounded. After adding the code, the distance between the "Cancel" button and other buttons disappeared. Also, the rounded corners of the pop-up window disappeared. It catches the eye. Other apps in dark mode don't have this problem. – Visal Kazymov Jul 21 '23 at 16:11
  • @lemonator21 I think it is necessary to make a custom confirmationDialog. On the site I saw a guy do this just for alert. And everything worked great. Unfortunately, my knowledge is not enough to write it myself. – Visal Kazymov Jul 21 '23 at 16:14
  • I see, well in that case you'll have to use UIAlertController instead. – devdchaudhary Jul 21 '23 at 17:03
  • 1
    all good, it's not good to include UIKit dependancies in a SwiftUI View but over here it doesn't seem like there's any alternative. – devdchaudhary Jul 21 '23 at 22:18
0

You are reading colorScheme correctly:

@Environment(\.colorScheme) var colorScheme

but then you don‘t use it. Instead of your variable isDarkMode, use colorScheme == .dark in your color modifiers to adapt your view to the color scheme.

In your example:


import SwiftUI

struct SettingListView: View, Themeable {
    @Environment(\.dismiss) var dismiss
    @State private var showingConfirmation = false
    @Environment(\.colorScheme) var colorScheme
    // @AppStorage("isDarkMode") private var isDarkMode = false // not neccessary
    @StateObject var settingsListViewModel = SettingsListViewModel()
    @State private var changeValueID = true
    @State private var showContacts = true
    
    var body: some View {
        NavigationStack {
            List {
                Section {
                    VStack {
                        ZStack(alignment: .bottomTrailing) {
                            Image("avatar")
                                .resizable()
                                .scaledToFill()
                                .frame(width: 120, height: 120)
                                .clipShape(Circle())
                                .onTapGesture {
                                    showingConfirmation = true
                                }
                                .confirmationDialog("Change Profile Picture", isPresented: $showingConfirmation, titleVisibility: .visible) {
                                    Button(role: .none, action: {}) {
                                        Text("Take Photo")
                                    }
                                    Button(role: .none, action: {}) {
                                        Text("Choose from library")
                                    }
                                    Button(role: .none, action: {}) {
                                        Text("Use Avatar")
                                    }
                                }
                            Image(systemName: "pencil")
                                .foregroundColor(colorScheme ? .white : .black) // use colorScheme
                                .frame(width: 28, height: 28)
                                .background(colorScheme ? Color(#colorLiteral(red: 0.370555222, green: 0.3705646992, blue: 0.3705595732, alpha: 1)) : Color(#colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1))) // use colorScheme
                                .clipShape(Circle())
                                .overlay {
                                    Circle().stroke(isDarkMode ? .black : Color(.secondarySystemBackground), lineWidth: 4)
                                }
                                .scaleEffect(x: 1.1, y: 1.1, anchor: .center)
                        }
                    }


——-

A simpler option without reading environment value colorScheme is to leave color choice to the system with semantic colors:

 .foregroundColor(.primary)

Leave out .background(Color…) in that case

soundflix
  • 928
  • 9
  • 22