Подскакивающий таймер обратного отсчета SwiftUI (таймер меняет свой размер, когда время истекает)IOS

Программируем под IOS
Ответить Пред. темаСлед. тема
Anonymous
 Подскакивающий таймер обратного отсчета SwiftUI (таймер меняет свой размер, когда время истекает)

Сообщение Anonymous »

Таймер меняет свой размер, когда время истекает, например с 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
)
}
}



Подробнее здесь: https://stackoverflow.com/questions/786 ... e-runs-out
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «IOS»