[SWIFT] iOS App Entwicklung: Timer App (6. Erstellung des Einstellungsbildschirms)

スクリーンショット 2020-10-28 11.14.23.png

Artikel

Die Punkte zum Erstellen einer Timer-App werden in mehreren Artikeln veröffentlicht. In diesem Artikel werde ich Ihnen zeigen, wie Sie einen Einstellungsbildschirm erstellen, der das Ein- und Ausschalten des Alarmtons und das Ein- und Ausschalten des Fortschrittsbalkens umfasst.

Umgebung

Git-Repository

Sie können den Beispielcode unter der folgenden Git-Repository-URL sehen. https://github.com/msnsk/Qiita_Timer.git

Verfahren

  1. Listen Sie die Einstellungselemente auf
  2. Erstellen Sie SettingView
  3. Erstellen Sie eine Liste in SettingView
  4. Fügen Sie das Einstellungselement zur Liste von SettingView hinzu
  5. Fügen Sie TimeManager Eigenschaften hinzu, die für verschiedene Einstellungen erforderlich sind
  6. Verknüpfen Sie die SettingView-Einstellungen mit den TimeManager-Eigenschaften
  7. Machen Sie SettingView modal
  8. Fügen Sie MainView eine Einstellungsschaltfläche hinzu und zeigen Sie den Einstellungsbildschirm modal an

Detaillierte Vorgehensweise

1. Listen Sie die Einstellungselemente auf

Wir werden einen Einstellungsbildschirm erstellen. Die PickerView, TimerView und ButtonsView, die ich bisher erstellt habe, werden alle in der MainView platziert, und die Timer-App hat keinen anderen Bildschirm als die MainView.

Dieses Mal erstellen wir einen Einstellungsbildschirm getrennt von MainView. Die folgenden Elemente werden auf diesem Einstellungsbildschirm angezeigt.

2. Erstellen Sie eine Einstellungsansicht

Erstellen Sie aus der SwiftUI-Vorlage eine neue Datei mit dem Namen SettingView.

Auch hier werden die Einstellungsinformationen möglicherweise in den Eigenschaften der TimeManager-Klasse wiedergegeben. Fügen Sie daher zuerst den Eigenschafts-Wrapper @EnvironmentObject hinzu, um eine Instanz von TimeManager zu erstellen.

SettingView.swift


import SwiftUI

struct SettingView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
        Text("Hello, World!")
    }
}

3. Erstellen Sie eine Liste in SettingView

Es gibt zwei Haupttypen von Komponenten, die für die Listenanzeige in SwiftUI verwendet werden. Eines ist List und das andere ist Form.

Form wird für den Einstellungsbildschirm allgemeiner iOS-Apps verwendet, daher verwenden wir dieses Mal Form.

Selbst wenn Sie einige Abschnitte durch Titel unterteilen, wird die Liste mit allen Abschnitten einschließlich der durch Ränder getrennten Abschnittsunterteilungen angezeigt, sodass sie besser zum Anordnen von Elementen wie Erinnerungen in einer Reihe geeignet ist. ..

Für das Element zur Auswahl des Alarmtons möchten wir vom Einstellungsbildschirm zum Tonauswahlbildschirm wechseln. Fügen Sie daher die Formularkomponente in die Navigationsansicht ein. Auf diese Weise ist es möglich, den Übergang innerhalb des Formulars zu einer anderen Liste oder einem anderen Formular zu konfigurieren.

SettingView.swift


struct SettingView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
        NavigationView {
            Form {
            }
        }
    }
}

4. Fügen Sie das Einstellungselement zur Liste von SettingView hinzu

Die Bildschirmkonfiguration wird wie folgt angenommen.

Abschnitt 1: Alarmbezogen </ strong>

  • Kippschalter für Alarmton ein / aus
  • Ein- / Ausschalter für Vibration
  • Auswahl des Alarmtons

Abschnitt 2: Animationsbezogen </ strong>

  • Fortschrittsbalkenanzeige Ein / Aus-Kippschalter --Effekt-Ein- / Ausschalter für Animation
  • Die eigentliche Implementierung von Abschnitt 2 erfolgt nach dem Erstellen des Einstellungsbildschirms.

Abschnitt 3: Schließen Sie den Einstellungsbildschirm </ strong>

  • Schaltfläche zum Schließen des Einstellungsbildschirms

Fügen Sie drei Abschnitte in das Formular ein. Der erste Abschnitt enthält zwei Toggle- und einen NavigationLink. Setzen Sie einen Toggle in den zweiten Abschnitt. Setzen Sie einen Knopf in den dritten Abschnitt.

Wenn Sie den Titel des Abschnitts in Text in die Argumentkopfzeile von Abschnitt einfügen, ist es einfacher zu verstehen, um welchen Abschnitt es sich handelt.

SettingView.swift


struct SettingView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Alarm:")) {
                    Toggle(isOn: ) {
                    }
                    Toggle(isOn: ) {
                    }
                    NavigationLink(destination: )) {
                    }
                }
                Section(header: Text("Animation:")) {
                    Toggle(isOn: ) {
                    }
                    Toggle(isOn: ) {
                    }
                }
                Section(header: Text("Save:")) {
                    Button(action: ) { 
                    }
                }
            }
        }
    }
}

Jetzt benötigen wir eine Eigenschaft, die das Ein- und Ausschalten der Toggle-Komponente widerspiegelt. Diese Eigenschaft muss in jeder Komponente von MainView auf dem Einstellungsbildschirm angezeigt werden. Wenn Sie beispielsweise einen Alarm auf dem Einstellungsbildschirm aktivieren, wird die Einstellung tatsächlich in MainView ausgelöst.

Daher muss die Eigenschaft, in der die einzelnen Einstellungsinformationen gespeichert sind, mit dem Eigenschafts-Wrapper @Published zur TimeManager-Klasse hinzugefügt werden.

5. Fügen Sie TimeManager Eigenschaften hinzu, die für verschiedene Einstellungen erforderlich sind

Fügen Sie TimeManager vier Eigenschaften hinzu, um Konfigurationsinformationen für Kippschalter zu speichern. Die folgenden vier Elemente werden hinzugefügt.

  • Einstellung für Alarmton ein / aus
  • Ein- / Ausschalten der Vibration
  • Ein- / Ausschalten der Fortschrittsbalkenanzeige --Ein / Aus-Einstellung der Animationsanzeige beeinflussen

TimeManager.swift


class TimeManager: ObservableObject {
    //(Andere Eigenschaften weggelassen)

    //Speichert den Soundnamen, der dem Wert der soundID-Eigenschaft entspricht
    @Published var soundName: String = "Beat"

    //Alarmton ein/Aus Einstellung
    @Published var isAlarmOn: Bool = true
    //Vibration an/Aus Einstellung
    @Published var isVibrationOn: Bool = true
    //Fortschrittsbalkenanzeige ein/Aus Einstellung
    @Published var isProgressBarOn: Bool = true
    //Effektanimationsanzeige ein/Aus Einstellung
    @Published var isEffectAnimationOn: Bool = true

    //Die Veröffentlichungsmethode der Timer-Klasse, die jede Sekunde aktiviert wird
    var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    //(Methode weggelassen)
}

6. Verknüpfen Sie die SettingView-Einstellungen mit den TimeManager-Eigenschaften

Geben Sie im Argument der Umschaltmethode isOn die Eigenschaft des TimeManager an, für den Sie die Einstellungen speichern möchten. Zu diesem Zeitpunkt müssen Sie dem Symbol $ das Präfix voranstellen. Geben Sie außerdem im Abschluss den Namen ein, den Sie als Einstellungselement im Formular mit Text anzeigen möchten.

Toggle(isOn: $timeManager.isAlarmOn) {
         Text("Alarm Sound")
 }

Auf diese Weise werden wir vorerst alle Toggle-Argumente und -Verschlüsse beschreiben.

In Bezug auf das Auswahlelement für den Alarmton gibt es noch keinen Auswahlbildschirm. Kommentieren Sie ihn daher einmal aus.

Die Beschriftung für die letzte Schaltfläche zum Speichern ist mit Text und einem Häkchensymbol versehen. Da wir es in horizontaler Richtung in der Mitte platzieren möchten, bringen wir es in die Mitte, indem wir es mit HStack umgeben und Spacer von links und rechts platzieren. Die Aktion beim Tippen auf die Schaltfläche ist noch leer.

SettingView.swift


struct SettingView: View {
    @EnvironmentObject var timeManager: TimeManager
    
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Alarm:")) {
                    Toggle(isOn: $timeManager.isAlarmOn) {
                        Text("Alarm Sound")
                    }
                    Toggle(isOn: $timeManager.isVibrationOn) {
                        Text("Vibration")
                    }
//                    NavigationLink(destination: ) {
//
//                    }
                }
                Section(header: Text("Animation:")) {
                    Toggle(isOn: $timeManager.isProgressBarOn) {
                        Text("Progress Bar")
                    }
                    Toggle(isOn: $timeManager.isEffectAnimationOn) {
                        Text("Effect Animation")
                    }
                }
                Section(header: Text("Save:")) {
                    Button(action: ) {
                        HStack {
                            Spacer()
                            Text("Done")
                            Image(systemName: "checkmark.circle")
                            Spacer()
                        }
                    }
                }
            }
        }
    }
}

Überprüfen Sie die Anzeige von SettingView auf Leinwand. Unten ist der Code für die Vorschau.

struct SettingView_Previews: PreviewProvider {
    static var previews: some View {
        SettingView().environmentObject(TimeManager())
    }
}

Es sollte wie im Bild unten aussehen. スクリーンショット 2020-10-28 11.14.35.png

7. Machen Sie SettingView modal

Zeigen Sie die SettingView modal an. Modal ist ein verkürzter Name für ein Modalfenster, der so aussieht, als wäre er bei geöffnetem Fenster nicht funktionsfähig.

Bereiten Sie eine Variable mit einem Eigenschafts-Wrapper namens @Environment (\ .presentationMode) in SettingView vor.

Schreiben Sie als Nächstes den Code, um das Modal beim Schließen des Aktionsarguments der Schaltfläche Speichern zu schließen, auf das beim Schließen des Einstellungsbildschirms getippt wird.

self.presentationMode.wrappedValue.dismiss()

SettingView.swift


struct SettingView: View {
    //Eigenschaften für die Verwendung von Modalblättern
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var timeManager: TimeManager
    
    var body: some View {
        NavigationView {
            Form {
                //(Andere Abschnitte weggelassen)

                Section(header: Text("Save:")) {
                    Button(action: { 
                        //Tippen Sie auf, um Modal zu schließen
                        self.presentationMode.wrappedValue.dismiss()
                    }) {
                        HStack {
                            Spacer()
                            Text("Done")
                            Image(systemName: "checkmark.circle")
                            Spacer()
                        }
                    }
                }
            }
        }
    }
}

Im Gegenteil, dieses Mal bereiten wir eine Schaltfläche in MainView vor, um den Einstellungsbildschirm zu öffnen. Erstellen Sie mit nur einer Schaltfläche eine leicht verständliche Ansicht. Jetzt erstellen wir eine neue SwiftUI-Datei mit dem Namen SettingButton.

SettingButtonView.swift


import SwiftUI

struct SettingButtonView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
    }
}

Das Schaltflächensymbol verwendet "ellipsis.circle.fill" von SF Symbols.

SettingButtonView.swift


import SwiftUI

struct SettingButtonView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
        Image(systemName: "ellipsis.circle.fill")
    }
}

Die Größe der Einstellungstaste ist geringfügig kleiner als die der Start- / Pause-Taste und der Reset-Taste. Verwenden Sie daher den Frame-Modifikator, um die vertikalen und horizontalen Größen einzustellen.

SettingButtonView.swift


import SwiftUI

struct SettingButtonView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
        Image(systemName: "ellipsis.circle.fill")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 40, height: 40)
    }
}

Erstellen Sie jetzt eine Bool-Typ-Eigenschaft in der TimeManager-Klasse, die das Modal ein- / ausblendet. Nennen Sie es Einstellung.

TimeManager.swift


class TimeManager: ObservableObject {
    //(Andere Eigenschaften weggelassen)

    //Anzeige des Einstellungsbildschirms/Ausblenden
    @Published var isSetting: Bool = false

    //(Methode weggelassen)
}

Kehren Sie schließlich zu SettingButtonView zurück und fügen Sie .onTapGesture hinzu, damit die isSetting-Eigenschaft des TimeManager innerhalb des Abschlusses {} wahr ist.

SettingButtonView.swift


import SwiftUI

struct SettingButtonView: View {
    @EnvironmentObject var timeManager: TimeManager

    var body: some View {
        Image(systemName: "ellipsis.circle.fill")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 40, height: 40)
            .onTapGesture {
                self.timeManager.isSetting = true
    }
}

Lassen Sie uns den Bildschirm mit Canvas überprüfen. Unten ist der Code für die Vorschau.

struct SettingButton_Previews: PreviewProvider {
    static var previews: some View {
        SettingButtonView()
            .environmentObject(TimeManager())
            .previewLayout(.sizeThatFits)
    }
}

Es sollte wie im Bild unten aussehen. スクリーンショット 2020-10-28 10.56.37.png

8. Fügen Sie MainView eine Einstellungsschaltfläche hinzu und zeigen Sie den Einstellungsbildschirm modal an

Fügen wir nun SettingButtonView zu ManiView hinzu.

Der hinzuzufügende Ort befindet sich am unteren Bildschirmrand wie die Schaltflächen Start / Pause und Zurücksetzen unter PickerView und TimerView. Daher werden in ZStack {} ButtonsView und SettingButtonView vor und zurück geschichtet. Es spielt keine Rolle, welche vorne oder hinten ist.

SettingBottonView fügt neben ButtonsView einen Padding-Modifikator (.bottom) hinzu, da es besser ist, alle Schaltflächen in vertikaler Richtung auszurichten.

Fügen Sie dann einen Modifikator .sheet () hinzu, um das modale Fenster anzuzeigen. Das Argument isPresented gibt eine Bool-Typ-Eigenschaft an, deren Modal angezeigt wird, wenn true. Das heißt, die isSetting-Eigenschaft der TimeManager-Klasse, die wir zuvor vorbereitet haben.

Beschreiben Sie im Abschluss {} die Ansicht, die Sie modal anzeigen möchten. Hier ist es SettingView (). Beschreiben Sie zu diesem Zeitpunkt auch die Eigenschaft .environmentObject (self.timeManager).

MainView.swift


struct MainView: View {
    @EnvironmentObject var timeManager: TimeManager
    
    var body: some View {
        ZStack {
            if timeManager.timerStatus == .stopped {
                PickerView()
            } else {
                TimerView()
            }
            
            VStack {
                Spacer()
                //Überlagern Sie ButtonsView und SettingButtonView in Ebenen
                ZStack {
                    ButtonsView()
                        .padding(.bottom)
                    //Einstellungsschaltfläche hinzugefügt
                    SettingButtonView()
                        .padding(.bottom)
                        //Zeigen Sie SettingView modal an, wenn die isSetting-Eigenschaft true ist
                        .sheet(isPresented: $timeManager.isSetting) {
                            SettingView()
                                            .environmentObject(self.timeManager)
                        }
                }
            }
        }
        //(.osReceive-Modifikatorteil weggelassen)
    }
}

Da wir Alarmton- und Vibrationseinstellungselemente hinzugefügt haben, wird ein Alarm ausgelöst, wenn der Timer im näheren Bereich des onReceive-Modifikators von MainView auf 0 gesetzt wird, und die Beschreibung zum Aktivieren der Vibration beschrieben, wenn die Einstellung eingeschaltet ist. Dies ist einfach eine bedingte Verzweigung in der if-Anweisung in Abhängigkeit von den Werten der Eigenschaften isAlarmOn und isVibrationOn der TimeManager-Klasse.

MainView.swift


struct MainView: View {
    @EnvironmentObject var timeManager: TimeManager
    
    var body: some View {
        ZStack {
            //(Beschreibung anzeigen weggelassen)
        }
        //Führt den Code im Abschluss aus, der von einem Timer ausgelöst wird, der jedes Mal aktiviert wird (1 Sekunde).
        .onReceive(timeManager.timer) { _ in
            //Der Timer-Status ist.Mach nichts außer rennen
            guard self.timeManager.timerStatus == .running else { return }
            //Wenn die verbleibende Zeit größer als 0 ist
            if self.timeManager.duration > 0 {
                //Von der verbleibenden Zeit-0.05
                self.timeManager.duration -= 0.05
                //Wenn die verbleibende Zeit 0 oder weniger beträgt
            } else {
                //Timer-Status.Wechseln Sie zu gestoppt
                self.timeManager.timerStatus = .stopped
                //Alarm auslösen
                if timeManager.isAlarmOn {
                    AudioServicesPlayAlertSoundWithCompletion(self.timeManager.soundID, nil)
                }
                //Vibration aktivieren
                if timeManager.isVibrationOn {
                    AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) {}
                }
            }
        }
    }
}

Lassen Sie uns die Hauptansicht mit Canvas überprüfen. Unten ist der Code für die Vorschau.

struct MainView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            MainView().environmentObject(TimeManager())
        }
    }
}

Es sollte wie im Bild unten aussehen. Die Einstelltaste befindet sich zwischen der Starttaste und der Reset-Taste mit derselben Höhe. スクリーンショット 2020-10-28 10.57.44.png

Wenn Sie nun auf die Einstellungsschaltfläche tippen, wird der Einstellungsbildschirm modal angezeigt. Bitte überprüfen Sie es mit Canvas.

Dieses Mal habe ich eine Ansicht mit nur Einstellungsschaltflächen als SettingButtonView erstellt, aber ich denke, es ist in Ordnung, sie in der zuvor erstellten ButtonsView zusammenzustellen.

Recommended Posts