Round iOS player seek bar and show scrubber only while dragging

Clip the progress bar with a Capsule for neater edges, and reveal the
scrubber handle only during a drag with a spring zoom animation.
This commit is contained in:
Arkadiusz Fal
2026-05-09 16:54:45 +02:00
parent d49591eaf4
commit 06ae5ac053

View File

@@ -844,6 +844,7 @@ struct PlayerControlsView: View {
Rectangle()
.fill(.red.opacity(0.6))
.frame(height: 4)
.clipShape(Capsule())
} else {
// Regular VOD progress bar with chapter segments
SegmentedProgressBar(
@@ -859,16 +860,17 @@ struct PlayerControlsView: View {
sponsorSegments: playerState.sponsorSegments,
sponsorBlockSettings: activeLayout.progressBarSettings.sponsorBlockSettings
)
.clipShape(Capsule())
// Scrubber handle - fixed 20x20 frame to prevent layout shift
// Hidden when controls are locked to show only the progress bar
// Scrubber handle - only visible while dragging, zooms in/out
Circle()
.fill(activeLayout.progressBarSettings.playedColor.color)
.frame(width: 20, height: 20)
.scaleEffect(isDragging ? 1.0 : 0.75)
.offset(x: geometry.size.width * displayProgress - 10, y: 8)
.animation(.easeInOut(duration: 0.1), value: isDragging)
.opacity(playerState.isControlsLocked ? 0 : 1)
.scaleEffect(isDragging ? 1.0 : 0.0)
.opacity(isDragging ? 1 : 0)
.offset(x: geometry.size.width * dragProgress - 10, y: 8)
.animation(.spring(response: 0.3, dampingFraction: 0.7), value: isDragging)
.allowsHitTesting(false)
}
}
.frame(height: 20)
@@ -998,15 +1000,6 @@ struct PlayerControlsView: View {
playerState.chapters.last { $0.startTime <= seekTime }
}
private var displayProgress: Double {
(isDragging || isPendingSeek) ? dragProgress : playerState.progress
}
private var bufferedProgress: Double {
guard playerState.duration > 0 else { return 0 }
return playerState.bufferedTime / playerState.duration
}
// MARK: - Timer Management
private func toggleControlsVisibility() {