Implementing Mini Player in Mobile Applications
Mini player — a strip with track title, play/pause buttons and progress bar, visible when navigating between screens. Looks simple, but technically hinges on navigation architecture: player must live outside specific screen and not recreate on transitions.
Architectural Solution
Mini player is not a screen but persisted overlay above the entire app. Placement depends on navigation system.
iOS (UIKit). Add mini player to UITabBarController or UIWindow — lives at container level, not specific ViewController. Limitation: UITabBar occupies bottom, mini player placed directly above it, shift additionalSafeAreaInsets.bottom for all VCs in tab.
// In custom UITabBarController
override func viewDidLoad() {
super.viewDidLoad()
miniPlayerView = MiniPlayerView()
view.addSubview(miniPlayerView)
NSLayoutConstraint.activate([
miniPlayerView.bottomAnchor.constraint(equalTo: tabBar.topAnchor),
miniPlayerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
miniPlayerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
miniPlayerView.heightAnchor.constraint(equalToConstant: 64)
])
// Shift safe area for child VCs
additionalSafeAreaInsets.bottom = 64
}
iOS (SwiftUI). ZStack in root ContentView with TabView at bottom and mini player above via .overlay(alignment: .bottom). Player state — @EnvironmentObject or @ObservedObject singleton.
Android (Jetpack Compose). Mini player in root Scaffold as bottomBar, or via Box above NavHost. State via ViewModel at NavGraph level — survives screen navigation.
React Native. Mini player component in root App.tsx above navigator. position: 'absolute', bottom: tabBarHeight + swipe gesture up for expand.
Expand/Collapse Animation
Mini player should expand to fullscreen player on tap or swipe up.
iOS. UIPanGestureRecognizer + UIViewPropertyAnimator with interruptibleAnimator. On intermediate states — fractionComplete animates proportionally to finger movement. Apple Music does exactly this: fullscreen player is a sheet with detents, mini player is custom presentationController.
Android Compose. BottomSheetScaffold or ModalBottomSheet with custom sheetPeekHeight and sheetContent. At peekHeight — mini player, when expanded — full.
State Synchronization
Progress bar, track title, artwork — all must update in real-time regardless of which screen user is on. Single source of truth — PlayerViewModel / AudioPlayerManager as singleton with @Published (iOS) or StateFlow (Android). Mini player subscribes to it, doesn't store local state.
Gestures and Accessibility
Swipe down on expanded player — collapse/minimize to mini. Implement via UIPanGestureRecognizer (iOS) with threshold translation.y > 100 to confirm action. On incomplete swipe — UIViewPropertyAnimator returns to original state.
On Android Compose — swipeable (from accompanist) or anchoredDraggable (Compose 1.6+) with anchors COLLAPSED / EXPANDED. On gesture speed > 1000 dp/s — immediate transition without animation.
VoiceOver/TalkBack: mini player should have accessibilityLabel with current track and accessibilityHint "Tap to open full player". Pause button in mini player — separate accessibilityElement.
Timeline
Mini player with expand animation on one platform — 2–3 days. Both platforms with gesture control — 3–4 days.







