Проблема: плеєр зникає під час навігації
Ви розробляєте музичний застосунок і помічаєте: при переході з екрана треків на сторінку налаштувань плеєр зникає — він перестворюється разом з ViewController. Користувач втрачає контекст відтворення і часто кидає прослуховування. За 5 років роботи ми стикалися з цим у десятках проєктів і виробили рішення — міні-плеєр з persistent overlay, який живе поза навігаційним стеком. Наша команда сертифікованих розробників iOS та Android реалізувала такі плеєри більш ніж у 100 проєктах, скоротивши кількість багів з десинхронізацією прогресу на 80% в одному з них.
Як міні-плеєр вирішує проблему втрати контексту?
Міні-плеєр — це lightweight view, закріплений на рівні вікна або кореневого контейнера. Він не залежить від зміни екранів і залишається видимим при будь-яких переходах. На iOS ми розміщуємо його поверх tabBar, на Android — у кореневому Box. Така архітектура гарантує, що користувач завжди бачить поточний трек і може керувати відтворенням, не відволікаючись від контенту.
Чому синхронізація стану критична?
Якщо міні-плеєр не синхронізований з основним плеєром, прогрес і стан відтворення розходяться. Користувач бачить один трек, а чує інший. Єдине джерело істини — синглтон PlayerViewModel (iOS) або StateFlow (Android). Міні-плеєр підписується на зміни через @Published або collectAsState(). В одному проєкті такий підхід скоротив кількість багів з десинхронізацією прогресу на 80%.
Як ми реалізуємо міні-плеєр
iOS (UIKit)
Додаємо міні-плеєр у кастомний UITabBarController як subview над tabBar. Зсув additionalSafeAreaInsets.bottom компенсує висоту плеєра у дочірніх контролерів.
// В кастомному 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) ]) // Зсуваємо safe area для дочірніх VC additionalSafeAreaInsets.bottom = 64 } iOS (SwiftUI)
Використовуємо .overlay(alignment: .bottom) на кореневому TabView. Стан плеєра — @EnvironmentObject синглтон. Анімація розгортання — matchedGeometryEffect для плавного переходу: це в 1.5 рази скорочує код порівняно з UIKit.
Android (Jetpack Compose)
Розміщуємо міні-плеєр у кореневому Box поверх NavHost. Для жестів використовуємо anchoredDraggable з якорями COLLAPSED та EXPANDED. ModalBottomSheet з sheetPeekHeight задає висоту міні-плеєра. Час розробки — 2–3 дні.
React Native
Міні-плеєр — абсолютний компонент з position: absolute та bottom, рівним висоті таб-бара. Анімація — Animated.View з PanResponder. Підходить для кроссплатформенних проєктів, але дає меншу гнучкість анімацій.
Етапи впровадження міні-плеєра
| Етап | Опис | Строк |
|---|---|---|
| Аналіз | Вивчення поточної архітектури навігації та аудіоплеєра | 1 день |
| Проєктування | Визначення шару overlay та способу синхронізації | 0.5 дня |
| Реалізація | Розробка міні-плеєра з анімаціями та жестами | 2-3 дні |
| Інтеграція | Підключення до існуючого плеєра та тестування | 1 день |
| Деплой | Публікація в App Store / Google Play | 0.5 дня |
Порівняння підходів: UIKit vs SwiftUI vs Compose
| Платформа | Надійність | Час розробки | Гнучкість анімацій |
|---|---|---|---|
| UIKit | Висока | 2-3 дні | Середня (UIViewPropertyAnimator) |
| SwiftUI | Середня | 1-2 дні | Висока (matchedGeometryEffect) |
| Compose | Висока | 2-3 дні | Висока (animate*AsState) |
| React Native | Середня | 2-3 дні | Середня (Animated API) |
SwiftUI швидше в розробці, але поступається UIKit у надійності при складних жестах. Compose поєднує високу надійність та гнучкість.
Жести та доступність
Свайп вгору для розгортання, вниз для згортання. На iOS — UIGestureRecognizer з порогом translation.y > 100. На Android Compose — swipeable з якорями. VoiceOver/TalkBack: accessibilityLabel та accessibilityHint. Кнопка паузи — окремий елемент.
Типові помилки при реалізації
| Помилка | Рішення |
|---|---|
| Перекриття клавіатури | Зафіксувати bottom з урахуванням keyboard insets |
| Ігнорування safeAreaInsets на iPhone X+ | Використовувати safeAreaLayoutGuide в UIKit або WindowInsets в Compose |
| Відсутність синхронізації при фоновому завантаженні | Застосувати BackgroundTask на iOS або WorkManager на Android |
Що входить в роботу
- Аналіз поточної архітектури навігації
- Проєктування overlay-компонента під ключ
- Реалізація міні-плеєра з expand/collapse анімацією
- Інтеграція з існуючим аудіо-плеєром (AVPlayer, ExoPlayer)
- Налаштування жестів та accessibility
- Тестування на пристроях з різними версіями ОС
Строки та вартість
Розробка міні-плеєра на одній платформі — 2-3 дні. Для двох платформ з жестовим керуванням — 3-4 дні. Вартість розраховується індивідуально, залежить від складності анімацій та інтеграції з бекендом. Досвід нашої команди — 5+ років, сертифіковані розробники iOS та Android. Якщо вам потрібен міні-плеєр з нестандартними анімаціями, зв'яжіться з нами для обговорення. Замовте розробку міні-плеєра під ключ та отримайте консультацію.







