Table of Contents

  1. Introduction
  2. Setting Up the Project
  3. Exploring Dark Mode and Dynamic Colors
  4. Building the MoodBoard App UI
  5. Adding Dynamic Color Support
  6. Saving and Displaying Mood Entries
  7. Testing in Dark Mode
  8. Conclusion

Introduction

Welcome to this tutorial where we will explore Dark Mode and Dynamic Colors in SwiftUI by building a fun project: MoodBoard: A Dynamic Theme Journal. In this app, users will create mood entries and categorize them with different colors, which will automatically adapt to the light and dark mode preferences. By the end of this tutorial, you'll have a solid understanding of how to implement dark mode and dynamic color changes in SwiftUI.

Let's get started! 🎉


Setting Up the Project

1. Create a New SwiftUI Project

  • Open Xcode and create a new project.
  • Choose App as the template.
  • Name your project MoodBoard.
  • Set the interface to SwiftUI and life cycle to SwiftUI App.

2. Set the Deployment Target

In your project settings, make sure the deployment target is set to iOS 14.0 or higher to fully leverage SwiftUI and dark mode support.


Exploring Dark Mode and Dynamic Colors

1. What is Dark Mode?

Dark Mode is a UI feature that switches the background to a dark color while the text turns light. It helps reduce eye strain and conserves battery on OLED screens. In iOS, SwiftUI automatically handles most of the dark mode transitions.

2. What are Dynamic Colors?

Dynamic Colors are colors that automatically adjust to the light or dark environment. They ensure that your app's color scheme remains accessible and visually appealing in both modes. SwiftUI allows you to define custom dynamic colors for your app.


Building the MoodBoard App UI

Let's start by creating the user interface for the app. We'll have a main view with a list of mood entries, a button to add a new entry, and a simple detail view for each mood.

1. Define the Mood Entry Model

Create a file called MoodEntry.swift to define a simple model for each mood.

import Foundation

struct MoodEntry: Identifiable {
    var id = UUID()
    var title: String
    var description: String
    var color: Color
}

2. Create the Main View (ContentView.swift)

In ContentView.swift, let's display a list of mood entries and provide a button to add a new entry.

import SwiftUI

struct ContentView: View {
    @State private var moodEntries: [MoodEntry] = []

    var body: some View {
        NavigationView {
            List(moodEntries) { entry in
                NavigationLink(destination: MoodDetailView(entry: entry)) {
                    Text(entry.title)
                        .padding()
                        .background(entry.color)
                        .cornerRadius(10)
                        .foregroundColor(.white)
                }
            }
            .navigationTitle("MoodBoard")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: addMoodEntry) {
                        Image(systemName: "plus.circle.fill")
                            .font(.title)
                    }
                }
            }
        }
    }

    func addMoodEntry() {
        // We'll add functionality to create a new mood entry later
    }
}

In this basic view, we have a list of mood entries with a navigation link to a detail view for each entry. The "+" button will allow us to add new moods.


Adding Dynamic Color Support

1. Define a Color Scheme for Dark and Light Mode

SwiftUI provides a way to specify colors that adapt to both light and dark mode using the Color struct. Let’s add some custom colors in Assets.xcassets.

  • Open Assets.xcassets in your Xcode project.
  • Add a new Color Set for each of the following: primaryBackground, secondaryBackground, and moodColor.
  • Set different color values for Light and Dark appearances.

For example:

  • primaryBackground: Light color is white, Dark color is black.
  • moodColor: Light color is blue, Dark color is green.

2. Modify the MoodEntry Model to Use Dynamic Colors

In MoodEntry.swift, update the MoodEntry model to use dynamic colors:

import SwiftUI

struct MoodEntry: Identifiable {
    var id = UUID()
    var title: String
    var description: String
    var color: Color = Color("moodColor")
}

Now the moodColor will automatically switch between light and dark mode.

3. Apply Dynamic Colors in the UI

Update ContentView.swift to use dynamic colors for the background and list items:

var body: some View {
    NavigationView {
        List(moodEntries) { entry in
            NavigationLink(destination: MoodDetailView(entry: entry)) {
                Text(entry.title)
                    .padding()
                    .background(entry.color)
                    .cornerRadius(10)
                    .foregroundColor(.white)
            }
            .listRowBackground(Color("primaryBackground"))
        }
        .navigationTitle("MoodBoard")
        .background(Color("primaryBackground"))
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button(action: addMoodEntry) {
                    Image(systemName: "plus.circle.fill")
                        .font(.title)
                }
            }
        }
    }
}

4. Testing Dynamic Colors

To test dynamic colors, simply toggle the device's appearance between Light and Dark mode in the Simulator or Xcode Preview.


Saving and Displaying Mood Entries

Next, let's allow the user to add mood entries. We'll use a form where users can enter the title, description, and choose a mood color.

1. Create a View for Adding a Mood Entry

Create a new view called MoodDetailView.swift to let the user add a new mood entry:

import SwiftUI

struct MoodDetailView: View {
    @State private var title = ""
    @State private var description = ""
    @State private var moodColor: Color = Color("moodColor")

    var body: some View {
        Form {
            Section(header: Text("Mood Details")) {
                TextField("Title", text: $title)
                TextField("Description", text: $description)
                ColorPicker("Mood Color", selection: $moodColor)
            }

            Button("Save") {
                // Save the mood entry
            }
        }
        .navigationTitle("New Mood Entry")
    }
}

This form allows the user to input a title, description, and select a color using the ColorPicker.

2. Save the Mood Entry

To save the mood entry, update the ContentView.swift to handle adding a new entry. When the user taps the "Save" button, create a new MoodEntry and add it to the list.

func addMoodEntry() {
    let newEntry = MoodEntry(title: title, description: description, color: moodColor)
    moodEntries.append(newEntry)
}

Testing in Dark Mode

To test your app's dark mode functionality:

  1. In the Simulator, go to Features > Toggle Appearance to switch between dark and light mode.
  2. In Xcode Preview, click the "Environment Overrides" button at the bottom and select Dark/Light mode.

Make sure all dynamic colors adapt correctly when switching modes! 🌙🌞


Conclusion

Congratulations! 🎉 You've now built the MoodBoard app with support for Dark Mode and Dynamic Colors using SwiftUI. You've learned how to define dynamic colors, apply them to your app's UI, and ensure your app adapts to both light and dark environments.

I hope this tutorial helped you understand the fundamentals of working with dark mode and dynamic colors in SwiftUI. Don't forget to experiment with other color sets and UI elements to take your app even further.

Happy coding! 💻✨