Dreamio turn document
Improve Center Play/Pause Indicator Contrast
Improved the native player center play/pause flash so it remains visible over varied video content.
Summary
Improved the native player center play/pause flash so it remains visible over varied video content.
Changes Made
- Made the center play/pause flash larger, darker, and more defined with a stronger border and shadow.
- Kept the indicator visible for longer during the flash animation and added a reduced-motion fade path.
Context
The center-screen play/pause indicator was too transparent, making it hard to see against bright or busy video frames.
Important Implementation Details
- The existing Liquid Glass-style icon button remains in use, but the transient center instance now gets a high-contrast black backing instead of the low-alpha shared control treatment.
- The hit target and visual footprint increased from 68 to 80 points while keeping the indicator centered.
- Reduced Motion users now still receive a non-scaling visible flash instead of skipping the indicator entirely.
Relevant Diff Snippets
Dreamio/NativePlayerViewController.swift · center play/pause indicator contrast
343 unmodified lines34434534634734834935064 unmodified lines415416417418419420421422404 unmodified lines827828829830831832833834835836837838839343 unmodified linesaudioButton.showsMenuAsPrimaryAction = truecaptionsButton.showsMenuAsPrimaryAction = trueplayPauseButton.layer.cornerRadius = 28centerPlayPauseButton.layer.cornerRadius = 34centerPlayPauseButton.alpha = 0scrubber.addTarget(self, action: #selector(scrubbingStarted), for: .touchDown)scrubber.addTarget(self, action: #selector(scrubberChanged), for: .valueChanged)64 unmodified linescenterPlayPauseButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),centerPlayPauseButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),centerPlayPauseButton.widthAnchor.constraint(equalToConstant: 68),centerPlayPauseButton.heightAnchor.constraint(equalToConstant: 68),closeButton.widthAnchor.constraint(equalToConstant: 44),closeButton.heightAnchor.constraint(equalToConstant: 44),404 unmodified linesprivate func flashCenterPlayPauseIcon() {centerPlayPauseButton.setImage(UIImage(systemName: backend.isPlaying ? "pause.fill" : "play.fill"), for: .normal)guard !UIAccessibility.isReduceMotionEnabled else { return }centerPlayPauseButton.transform = CGAffineTransform(scaleX: 0.86, y: 0.86)UIView.animate(withDuration: 0.16, animations: {self.centerPlayPauseButton.alpha = 1self.centerPlayPauseButton.transform = .identity}) { _ inUIView.animate(withDuration: 0.22, delay: 0.28, options: [.curveEaseOut]) {self.centerPlayPauseButton.alpha = 0}}343 unmodified lines34434534634734834935035135235335435535635764 unmodified lines422423424425426427428429404 unmodified lines834835836837838839840841842843844845846847848849850851852853343 unmodified linesaudioButton.showsMenuAsPrimaryAction = truecaptionsButton.showsMenuAsPrimaryAction = trueplayPauseButton.layer.cornerRadius = 28centerPlayPauseButton.layer.cornerRadius = 40centerPlayPauseButton.backgroundColor = UIColor.black.withAlphaComponent(0.58)centerPlayPauseButton.layer.borderColor = UIColor.white.withAlphaComponent(0.38).cgColorcenterPlayPauseButton.layer.borderWidth = 1.5centerPlayPauseButton.layer.shadowColor = UIColor.black.cgColorcenterPlayPauseButton.layer.shadowOpacity = 0.45centerPlayPauseButton.layer.shadowRadius = 18centerPlayPauseButton.layer.shadowOffset = CGSize(width: 0, height: 8)centerPlayPauseButton.alpha = 0scrubber.addTarget(self, action: #selector(scrubbingStarted), for: .touchDown)scrubber.addTarget(self, action: #selector(scrubberChanged), for: .valueChanged)64 unmodified linescenterPlayPauseButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),centerPlayPauseButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),centerPlayPauseButton.widthAnchor.constraint(equalToConstant: 80),centerPlayPauseButton.heightAnchor.constraint(equalToConstant: 80),closeButton.widthAnchor.constraint(equalToConstant: 44),closeButton.heightAnchor.constraint(equalToConstant: 44),404 unmodified linesprivate func flashCenterPlayPauseIcon() {centerPlayPauseButton.setImage(UIImage(systemName: backend.isPlaying ? "pause.fill" : "play.fill"), for: .normal)if UIAccessibility.isReduceMotionEnabled {centerPlayPauseButton.transform = .identitycenterPlayPauseButton.alpha = 1UIView.animate(withDuration: 0.18, delay: 0.55, options: [.curveEaseOut]) {self.centerPlayPauseButton.alpha = 0}return}centerPlayPauseButton.transform = CGAffineTransform(scaleX: 0.82, y: 0.82)UIView.animate(withDuration: 0.16, animations: {self.centerPlayPauseButton.alpha = 1self.centerPlayPauseButton.transform = .identity}) { _ inUIView.animate(withDuration: 0.26, delay: 0.34, options: [.curveEaseOut]) {self.centerPlayPauseButton.alpha = 0}}
Diffs are generated with @pierre/diffs/ssr at documentation time. Each file diff stays inside its own shell so the page remains readable as a static HTML artifact.
Expected Impact for End-Users
Users should be able to quickly confirm play or pause state changes from the middle of the screen, even over bright scenes or high-motion content.
Validation
xcodebuild -workspace Dreamio.xcworkspace -scheme Dreamio -sdk iphonesimulator -configuration Debug build— succeeded.
Issues, Limitations, and Mitigations
- No known issues. This is a visual contrast adjustment scoped to the native player overlay.
New Changes as of 2026-05-26 22:22
Summary of changes
Softened the center play/pause flash from a black badge with a strong outline into a separate liquid-glass blur plate behind a clear icon button.
Why this change was made
The previous contrast fix made the transient center indicator visible, but overcorrected with a heavy black fill and outline. The revised treatment keeps the indicator readable while better matching the native Liquid Glass direction.
Code diffs
+ private let centerPlayPauseIndicator = NativePlayerViewController.centerGlassIndicator()
...
+ view.addSubview(centerPlayPauseIndicator)
view.addSubview(centerPlayPauseButton)
...
- centerPlayPauseButton.backgroundColor = UIColor.black.withAlphaComponent(0.58)
- centerPlayPauseButton.layer.borderColor = UIColor.white.withAlphaComponent(0.38).cgColor
- centerPlayPauseButton.layer.borderWidth = 1.5
+ centerPlayPauseButton.backgroundColor = .clear
+ centerPlayPauseButton.layer.borderWidth = 0
+ centerPlayPauseIndicator.alpha = 0
...
+ private static func centerGlassIndicator() -> UIVisualEffectView {
+ let view = glassPanel(cornerRadius: 34)
+ view.backgroundColor = UIColor.white.withAlphaComponent(0.08)
+ view.layer.borderColor = UIColor.white.withAlphaComponent(0.18).cgColor
+ view.layer.borderWidth = 0.75
+ view.isUserInteractionEnabled = false
+ return view
+ }
Related issues or PRs
No new Beads issue or PR was created for this small visual follow-up.
Follow-up Work
- None currently identified.