Таймер меняет свой размер, когда время истекает, например с 00:52 на 00:51, потому что он занимает меньше места. Как я могу запретить таймеру прыгать, когда он встречает числа, занимающие меньше места? Я хочу закрепить его посередине, чтобы он не мог двигаться. Большое спасибо.
import SwiftUI
import AVFoundation
struct TimerView: View {
@Binding var duration: TimeInterval
@Binding var isEMOTM: Bool // Neues Binding
@State private var remainingTime: TimeInterval = 0
@State private var preStartCountdownTime: TimeInterval = 10 // Umbenannte Variable für den initialen Countdown
@State private var timer: Timer?
@State private var isRunning: Bool = false
@State private var isCountdown: Bool = true
@State private var soundEffect: AVAudioPlayer?
var isCountUp: Bool = false
var isInterval: Bool = false
var isCustomTimer: Bool = false // Neues Flag für den CustomTimer
var highDuration: TimeInterval = 0
var lowDuration: TimeInterval = 0
var numberOfRounds: Int = 0
@State private var currentRound: Int = 0
@State private var isHighInterval: Bool = true
@Environment(\.presentationMode) var presentationMode
var body: some View {
GeometryReader { geometry in
let iconSize = min(geometry.size.width, geometry.size.height) * 0.15
VStack {
Spacer() // Push timer down
VStack {
Spacer()
Text(isCountdown ? "\(Int(preStartCountdownTime))" : timeString(remainingTime))
.font(.custom("digital-7", size: 150)) // Adjust .padding(.horizontal, 20)
.padding(.vertical, 5)
.background(.black.opacity(0.75))
.clipShape(.capsule)
.fixedSize() // Keep size constant
Spacer()
}
.frame(maxWidth: .infinity)
// Zeigt die aktuelle Runde an, nur wenn es ein Intervall- oder EMOTM-Timer ist
if isInterval || isEMOTM {
HStack {
// Text links unten ausrichten
Text("\(currentRound + 1) / \(numberOfRounds)")
.foregroundColor(.gray)
}
}
Spacer()
// Konfiguriert die Steuerungsschaltflächen
HStack(spacing: 20) {
Button(action: {
presentationMode.wrappedValue.dismiss() // Schließt die Ansicht
}) {
Image(systemName: "arrow.left.circle") // Symbol für Zurück
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.white)
.padding()
.frame(width: iconSize, height: iconSize)
.background(Color.gray)
.cornerRadius(10)
}
Button(action: {
if isRunning {
stopTimer() // Stoppt den Timer
} else {
if isCountdown {
startCountdown() // Startet den Countdown
} else {
startTimer() // Startet den Timer
}
}
}) {
Image(systemName: isRunning ? "pause.circle" : (isCountdown ? "play.circle" : "play.circle")) // Symbol für Start/Pause
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.white)
.padding()
.frame(width: iconSize, height: iconSize)
.background(isRunning ? Color.orange : Color.green)
.cornerRadius(10)
}
Button(action: {
resetTimer() // Setzt den Timer zurück
}) {
Image(systemName: "arrow.counterclockwise.circle") // Symbol für Zurücksetzen
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.white)
.padding()
.frame(width: iconSize, height: iconSize)
.background(Color.red)
.cornerRadius(10)
}
}
.padding(.horizontal)
}
.background(Color(.black)) // Hintergrundfarbe der Ansicht
}
.onAppear {
resetTimer() // Setzt den Timer zurück, wenn die Ansicht erscheint
}
}
// Startet den Countdown-Timer
private func startCountdown() {
stopTimer() // Stoppt den laufenden Timer
isRunning = true
isCountdown = true
preStartCountdownTime = 2 // Setzt die Countdown-Zeit (später ändern)
playSound(sound: "countdown") // Spielt den Countdown-Sound ab
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in // Erstellt einen wiederholenden Timer
if preStartCountdownTime == 4 {
playSound(sound: "racestart") // Spielt den Start-Sound ab, wenn 4 Sekunden verbleiben
}
if preStartCountdownTime > 0 {
preStartCountdownTime -= 1 // Reduziert die Countdown-Zeit um 1 Sekunde
print("Countdown: \(preStartCountdownTime)")
} else {
isCountdown = false
startTimer() // Startet den Haupt-Timer, wenn der Countdown endet
}
}
}
// Startet den Haupt-Timer
private func startTimer() {
stopTimer() // Stoppt den laufenden Timer
isRunning = true
playSound(sound: "start") // Spielt den Start-Sound ab
if isInterval {
remainingTime = isHighInterval ? highDuration : lowDuration // Setzt die Dauer für High- oder Low-Intervall
} else if isCustomTimer {
remainingTime = 0 // Setzt die Dauer für den CustomTimer
} else if isCountUp {
remainingTime = 0 // Setzt die Dauer für Count-Up
} else {
remainingTime = duration // Setzt die Dauer für Count-Down
}
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in // Erstellt einen wiederholenden Timer
if isInterval {
if remainingTime > 0 {
remainingTime -= 1 // Reduziert die verbleibende Zeit um 1 Sekunde
print("Timer running: \(remainingTime) seconds left")
} else {
if isHighInterval {
isHighInterval.toggle() // Wechselt zu Low-Intervall
remainingTime = lowDuration
print("Switching to low interval: \(remainingTime) seconds")
} else {
currentRound += 1 // Erhöht die Rundenzahl nach High- und Low-Intervall
if currentRound >= numberOfRounds {
stopTimer() // Stoppt den Timer, wenn alle Runden abgeschlossen sind
print("Completed all rounds")
return
}
isHighInterval.toggle() // Wechselt zu High-Intervall
remainingTime = highDuration
print("Switching to high interval: \(remainingTime) seconds")
}
}
} else if isCustomTimer {
if remainingTime < duration {
remainingTime += 1 // Erhöht die vergangene Zeit um 1 Sekunde
print("Custom Timer running: \(remainingTime) seconds passed")
} else {
stopTimer() // Stoppt den Timer, wenn die Dauer erreicht ist
print("Completed custom timer")
}
} else if isCountUp {
if remainingTime < duration {
remainingTime += 1 // Erhöht die vergangene Zeit um 1 Sekunde
print("Count-Up Timer running: \(remainingTime) seconds passed")
} else {
stopTimer() // Stoppt den Timer, wenn die Dauer erreicht ist
print("Completed count-up timer")
}
} else { //Countdown Struktur auch von Emom genutzt
if remainingTime > 0 {
remainingTime -= 1 // Reduziert die verbleibende Zeit um 1 Sekunde
print("Timer running: \(remainingTime) seconds left")
} else {
if isEMOTM {
currentRound += 1
if currentRound < numberOfRounds {
remainingTime = duration
} else {
stopTimer() // Stoppt den Timer
}
} else {
stopTimer() // Stoppt den Timer, wenn die Zeit abgelaufen ist
print("Timer completed")
}
}
}
}
}
// Setzt den Timer zurück
private func resetTimer() {
stopTimer() // Stoppt den laufenden Timer
if isInterval {
remainingTime = highDuration // Setzt die verbleibende Zeit auf die High-Intervall-Dauer
currentRound = 0 // Setzt die aktuelle Runde auf 0
isHighInterval = true
} else if isCustomTimer {
remainingTime = 0 // Setzt die verbleibende Zeit auf 0 für den CustomTimer
} else if isCountUp {
remainingTime = 0 // Setzt die verbleibende Zeit auf 0 für Count-Up
} else {
remainingTime = duration // Setzt die verbleibende Zeit auf die Dauer für Count-Down
}
isCountdown = true
preStartCountdownTime = 10 // Setzt den Countdown auf 10 Sekunden
print("Timer reset")
}
// Stoppt den Timer
private func stopTimer() {
isRunning = false
timer?.invalidate() // Invalidiert den Timer
timer = nil
print("Timer stopped")
}
// Formatiert die verbleibende Zeit als String
private func timeString(_ interval: TimeInterval) -> String {
let minutes = Int(interval) / 60
let seconds = Int(interval) % 60
return String(format: "%02d:%02d", minutes, seconds) // Gibt die Zeit im Format MM:SS zurück
}
// Spielt einen Soundeffekt ab
private func playSound(sound: String) {
guard let url = Bundle.main.url(forResource: sound, withExtension: "mp3") else {
print("Sound file not found: \(sound).mp3")
return
}
do {
soundEffect = try AVAudioPlayer(contentsOf: url)
soundEffect?.play() // Spielt den Sound ab
print("Playing sound: \(sound).mp3")
} catch {
print("Error playing sound: \(error.localizedDescription)")
}
}
}
// Vorschau der TimerView für das SwiftUI Preview
struct TimerView_Previews: PreviewProvider {
static var previews: some View {
TimerView(
duration: .constant(600),
isEMOTM: .constant(false), // Füge dieses Binding hinzu
isCountUp: false,
isInterval: true,
isCustomTimer: false, // Setze isCustomTimer auf false für die Vorschau
highDuration: 60,
lowDuration: 30,
numberOfRounds: 5 // Konfiguriert die Vorschau der TimerView
)
}
}
Таймер меняет свой размер, когда время истекает, например с 00:52 на 00:51, потому что он занимает меньше места. Как я могу запретить таймеру прыгать, когда он встречает числа, занимающие меньше места? Я хочу закрепить его посередине, чтобы он не мог двигаться. Большое спасибо. [code]
import SwiftUI import AVFoundation
struct TimerView: View { @Binding var duration: TimeInterval @Binding var isEMOTM: Bool // Neues Binding @State private var remainingTime: TimeInterval = 0 @State private var preStartCountdownTime: TimeInterval = 10 // Umbenannte Variable für den initialen Countdown @State private var timer: Timer? @State private var isRunning: Bool = false @State private var isCountdown: Bool = true @State private var soundEffect: AVAudioPlayer? var isCountUp: Bool = false var isInterval: Bool = false var isCustomTimer: Bool = false // Neues Flag für den CustomTimer var highDuration: TimeInterval = 0 var lowDuration: TimeInterval = 0 var numberOfRounds: Int = 0 @State private var currentRound: Int = 0 @State private var isHighInterval: Bool = true @Environment(\.presentationMode) var presentationMode
var body: some View { GeometryReader { geometry in let iconSize = min(geometry.size.width, geometry.size.height) * 0.15 VStack { Spacer() // Push timer down
// Konfiguriert die Steuerungsschaltflächen HStack(spacing: 20) { Button(action: { presentationMode.wrappedValue.dismiss() // Schließt die Ansicht }) { Image(systemName: "arrow.left.circle") // Symbol für Zurück .resizable() .aspectRatio(contentMode: .fit) .foregroundColor(.white) .padding() .frame(width: iconSize, height: iconSize) .background(Color.gray) .cornerRadius(10) }
Button(action: { if isRunning { stopTimer() // Stoppt den Timer } else { if isCountdown { startCountdown() // Startet den Countdown } else { startTimer() // Startet den Timer } } }) { Image(systemName: isRunning ? "pause.circle" : (isCountdown ? "play.circle" : "play.circle")) // Symbol für Start/Pause .resizable() .aspectRatio(contentMode: .fit) .foregroundColor(.white) .padding() .frame(width: iconSize, height: iconSize) .background(isRunning ? Color.orange : Color.green) .cornerRadius(10) }
Button(action: { resetTimer() // Setzt den Timer zurück }) { Image(systemName: "arrow.counterclockwise.circle") // Symbol für Zurücksetzen .resizable() .aspectRatio(contentMode: .fit) .foregroundColor(.white) .padding() .frame(width: iconSize, height: iconSize) .background(Color.red) .cornerRadius(10) } } .padding(.horizontal) } .background(Color(.black)) // Hintergrundfarbe der Ansicht } .onAppear { resetTimer() // Setzt den Timer zurück, wenn die Ansicht erscheint } }
// Startet den Countdown-Timer private func startCountdown() { stopTimer() // Stoppt den laufenden Timer isRunning = true isCountdown = true preStartCountdownTime = 2 // Setzt die Countdown-Zeit (später ändern) playSound(sound: "countdown") // Spielt den Countdown-Sound ab timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in // Erstellt einen wiederholenden Timer if preStartCountdownTime == 4 { playSound(sound: "racestart") // Spielt den Start-Sound ab, wenn 4 Sekunden verbleiben } if preStartCountdownTime > 0 { preStartCountdownTime -= 1 // Reduziert die Countdown-Zeit um 1 Sekunde print("Countdown: \(preStartCountdownTime)") } else { isCountdown = false startTimer() // Startet den Haupt-Timer, wenn der Countdown endet } } }
// Startet den Haupt-Timer private func startTimer() { stopTimer() // Stoppt den laufenden Timer isRunning = true playSound(sound: "start") // Spielt den Start-Sound ab
if isInterval { remainingTime = isHighInterval ? highDuration : lowDuration // Setzt die Dauer für High- oder Low-Intervall } else if isCustomTimer { remainingTime = 0 // Setzt die Dauer für den CustomTimer } else if isCountUp { remainingTime = 0 // Setzt die Dauer für Count-Up } else { remainingTime = duration // Setzt die Dauer für Count-Down }
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in // Erstellt einen wiederholenden Timer if isInterval { if remainingTime > 0 { remainingTime -= 1 // Reduziert die verbleibende Zeit um 1 Sekunde print("Timer running: \(remainingTime) seconds left") } else { if isHighInterval { isHighInterval.toggle() // Wechselt zu Low-Intervall remainingTime = lowDuration print("Switching to low interval: \(remainingTime) seconds") } else { currentRound += 1 // Erhöht die Rundenzahl nach High- und Low-Intervall if currentRound >= numberOfRounds { stopTimer() // Stoppt den Timer, wenn alle Runden abgeschlossen sind print("Completed all rounds") return } isHighInterval.toggle() // Wechselt zu High-Intervall remainingTime = highDuration print("Switching to high interval: \(remainingTime) seconds") } } } else if isCustomTimer { if remainingTime < duration { remainingTime += 1 // Erhöht die vergangene Zeit um 1 Sekunde print("Custom Timer running: \(remainingTime) seconds passed") } else { stopTimer() // Stoppt den Timer, wenn die Dauer erreicht ist print("Completed custom timer") } } else if isCountUp { if remainingTime < duration { remainingTime += 1 // Erhöht die vergangene Zeit um 1 Sekunde print("Count-Up Timer running: \(remainingTime) seconds passed") } else { stopTimer() // Stoppt den Timer, wenn die Dauer erreicht ist print("Completed count-up timer") } } else { //Countdown Struktur auch von Emom genutzt if remainingTime > 0 { remainingTime -= 1 // Reduziert die verbleibende Zeit um 1 Sekunde print("Timer running: \(remainingTime) seconds left") } else { if isEMOTM { currentRound += 1 if currentRound < numberOfRounds { remainingTime = duration } else { stopTimer() // Stoppt den Timer } } else { stopTimer() // Stoppt den Timer, wenn die Zeit abgelaufen ist print("Timer completed") } } } } }
// Setzt den Timer zurück private func resetTimer() { stopTimer() // Stoppt den laufenden Timer if isInterval { remainingTime = highDuration // Setzt die verbleibende Zeit auf die High-Intervall-Dauer currentRound = 0 // Setzt die aktuelle Runde auf 0 isHighInterval = true } else if isCustomTimer { remainingTime = 0 // Setzt die verbleibende Zeit auf 0 für den CustomTimer } else if isCountUp { remainingTime = 0 // Setzt die verbleibende Zeit auf 0 für Count-Up } else { remainingTime = duration // Setzt die verbleibende Zeit auf die Dauer für Count-Down } isCountdown = true preStartCountdownTime = 10 // Setzt den Countdown auf 10 Sekunden print("Timer reset") }
// Formatiert die verbleibende Zeit als String private func timeString(_ interval: TimeInterval) -> String { let minutes = Int(interval) / 60 let seconds = Int(interval) % 60 return String(format: "%02d:%02d", minutes, seconds) // Gibt die Zeit im Format MM:SS zurück }
// Spielt einen Soundeffekt ab private func playSound(sound: String) { guard let url = Bundle.main.url(forResource: sound, withExtension: "mp3") else { print("Sound file not found: \(sound).mp3") return } do { soundEffect = try AVAudioPlayer(contentsOf: url) soundEffect?.play() // Spielt den Sound ab print("Playing sound: \(sound).mp3") } catch { print("Error playing sound: \(error.localizedDescription)") } } }
// Vorschau der TimerView für das SwiftUI Preview struct TimerView_Previews: PreviewProvider { static var previews: some View { TimerView( duration: .constant(600), isEMOTM: .constant(false), // Füge dieses Binding hinzu isCountUp: false, isInterval: true, isCustomTimer: false, // Setze isCustomTimer auf false für die Vorschau highDuration: 60, lowDuration: 30, numberOfRounds: 5 // Konfiguriert die Vorschau der TimerView ) } }
Таймер меняет свой размер, когда время истекает, например с 00:52 на 00:51, потому что он занимает меньше места. Как я могу запретить таймеру прыгать, когда он встречает числа, занимающие меньше места? Я хочу закрепить его посередине, чтобы он не...
Я хочу, чтобы в уведомлении отображался таймер, который менялся каждую секунду. Он отлично работает на Android 12, но в Android 11 и более поздних версиях таймер останавливается, когда приложение закрывается или телефон переходит в режим ожидания...
Я хочу, чтобы в уведомлении отображался таймер, который менялся каждую секунду. Он отлично работает на Android 12, но в Android 11 и более поздних версиях таймер останавливается, когда приложение закрывается или телефон переходит в режим ожидания...
Я хочу, чтобы в уведомлении отображался таймер, который менялся каждую секунду. Он отлично работает на Android 12, но в Android 11 и более поздних версиях таймер останавливается, когда приложение закрывается или телефон переходит в режим ожидания...
Мне нужно остановить время с 02.00 до 0.00. Но оно остановилось на -1,59 или начало уменьшаться и дальше. В угловом машинописном тексте я написал приведенный выше код. что я сделал не так:
Осталось времени = В машинописном тексте Angular:...