TV App — aplikacja dla smart-telewizorów działająca na platformach Apple TV (tvOS) i Android TV (Google TV). W przeciwieństwie do aplikacji mobilnych, TV App projektowana jest z uwzględnieniem nawigacji za pomocą pilota, zarządzania fokusem (Focus Engine) i specyficznych wymagań interfejsu na dużym ekranie. Tworzenie odbywa się w Swift/SwiftUI dla Apple TV oraz w Kotlin z Leanback Library dla Android TV. Według danych Statista (2026), ponad 250 mln urządzeń na całym świecie działa na tych platformach, co czyni TV App perspektywiczną niszą dla programistów. Omówimy architekturę platform, zarządzanie fokusem, przykłady kodu i proces publikacji.
Najważniejsze
TV App — aplikacja przeznaczona do działania na platformach inteligentnych telewizorów: Apple TV (tvOS) i Android TV (Google TV). Kluczowa różnica w stosunku do aplikacji mobilnej — sposób interakcji. Użytkownik nie dotyka ekranu, a steruje interfejsem za pomocą pilota. Wszystkie elementy muszą być dostępne poprzez nawigację kierunkową (D-pad): góra, dół, lewo, prawo i przycisk wyboru.
Cechy tworzenia TV App: rozdzielczość ekranu — od Full HD (1920x1080) do 4K (3840x2160) z gęstością xhdpi (Android) lub @3x (Apple). Obowiązkowa strefa bezpieczna 5% od krawędzi w celu kompensacji over-scan (część obrazu może być ucięta przez telewizor). Brak ekranu dotykowego — wszystkie interakcje przez pilot lub gamepad. Fokus zawsze podświetla aktywny element. Pobór energii nie jest ograniczony baterią, ale aplikacja musi poprawnie obsługiwać przejście w tryb uśpienia. Według danych Statista (2026), globalny rynek smart TV przekracza 80% nowych telewizorów, przy czym Apple TV i Android TV zajmują ponad 250 mln urządzeń.
Kategorie aplikacji TV: serwisy wideo (Netflix, YouTube, Apple TV+), muzyka (Spotify, Apple Music), gry (Apple Arcade, Google Play Games), fitness (Apple Fitness+, Peloton), edukacja, wiadomości, pogoda, zdjęcia. Najpopularniejsza kategoria — streaming wideo, zajmująca 70% całkowitego czasu korzystania z smart TV.
tvOS — system operacyjny Apple dla dekodera Apple TV, oparty na iOS. Pierwsze wydanie — 2015 rok wraz z Apple TV 4. generacji. tvOS dzieli z iOS jądro XNU, frameworki Foundation, UIKit (w wersji zaadaptowanej) i mechanizm bezpieczeństwa App Sandbox. Tworzenie odbywa się w Swift z użyciem SwiftUI lub UIKit.
Główne komponenty tvOS:
Cykl życia aplikacji tvOS jest analogiczny do iOS: notRunning, foregroundActive, foregroundInactive, background. Cecha: aplikacja nie powinna żądać uprawnień tła bez potrzeby — system może wymusić zakończenie procesu w tle. Topologia nawigacji opiera się na UISplitViewController i UITabBarController z zakładkami „Strona główna”, „Szukaj”, „Biblioteka”, „Ustawienia”.
Android TV — wersja Androida zoptymalizowana dla telewizorów i dekoderów, po raz pierwszy zaprezentowana w 2014 roku. Od 2020 roku istnieje Google TV — nakładka na Android TV z nowym interfejsem, ale tworzenie aplikacji odbywa się na Android TV SDK, kompatybilnym z Google TV. Główny język — Kotlin, frameworki UI — Leanback Library (klasyczny) i Jetpack Compose for TV (eksperymentalny).
Kluczowe komponenty Android TV:
Różnice Android TV od mobilnego Androida: aplikacja obowiązkowo deklaruje kategorię LEANBACK_LAUNCHER w manifeście; minimalna szerokość układu — 1920dp; interakcja dotykowa zastąpiona nawigacją D-pad; zaleca się używanie fragmentów Leanback; akceleracja sprzętowa jest obowiązkowa. Budowanie obejmuje APK/AAB z obsługą architektur ARM64 i x86. Dla nowoczesnych projektów od 2025 roku zaleca się Jetpack Compose for TV z komponentami TvLazyColumn, TvButton, TvCard.
Focus Engine — kluczowy komponent każdej platformy TV, odpowiadający za to, który element interfejsu jest aktywny. Na tvOS Focus Engine jest wbudowany w UIKit i działa automatycznie. Po naciśnięciu przycisku D-pad system analizuje położenie wszystkich focusable-elementów, oblicza najbliższego kandydata w kierunku naciśnięcia i płynnie przenosi na niego fokus z animacją (UIFocusAnimationCoordinator).
Zasady Focus Engine: system uwzględnia odległość między elementami wzdłuż osi ruchu, przecięcie projekcji elementów (element jest uznawany za kandydata, jeśli jego projekcja przecina projekcję bieżącego fokusu), priorytet elementów o tej samej odległości (wybierany jest najbliższy w linii prostej). Programista może wpływać na fokus za pomocą UIFocusGuide — niewidzialnego prostokąta prowadzącego, przekierowującego fokus na konkretny element po naciśnięciu w zadanym kierunku.
Na Android TV fokus jest realizowany poprzez standardowy system fokusu Androida z atrybutami focusable i nextFocus* (nextFocusDown, nextFocusUp, nextFocusLeft, nextFocusRight). Animacja konfigurowana jest przez StateListAnimator. Google zaleca ustawianie focusable na wszystkich interaktywnych elementach i używanie nextFocus do precyzyjnego sterowania nawigacją. Animacja fokusu jest krytyczna dla UX — przy przejściu fokusu powinna następować płynna animacja skalowania (1.0 → 1.05–1.2) z czasem trwania 150–250 ms.
Przykład prostej aplikacji TV w SwiftUI dla Apple TV z wyświetlaniem listy filmów i obsługą Focus Engine.
import SwiftUI
struct Movie: Identifiable {
let id = UUID()
let title: String
let subtitle: String
}
struct ContentView: View {
@FocusState private var focusedMovie: UUID?
let movies: [Movie] = [
Movie(title: "Inception", subtitle: "2010, Sci-Fi"),
Movie(title: "Interstellar", subtitle: "2014, Sci-Fi"),
Movie(title: "The Matrix", subtitle: "1999, Action"),
Movie(title: "Blade Runner 2049", subtitle: "2017, Sci-Fi"),
]
var body: some View {
VStack(alignment: .leading, spacing: 40) {
Text("Filmy").font(.title).padding(.leading, 60)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 40) {
ForEach(movies) { movie in
VStack {
Image(systemName: "film.fill")
.resizable()
.frame(width: 200, height: 300)
.cornerRadius(12)
.focusable()
.focused($focusedMovie, equals: movie.id)
Text(movie.title).font(.headline)
Text(movie.subtitle).font(.subheadline).foregroundColor(.secondary)
}
.scaleEffect(focusedMovie == movie.id ? 1.15 : 1.0)
.animation(.easeInOut(duration: 0.2), value: focusedMovie)
}
}
.padding(.horizontal, 60)
}
}
.onAppear { focusedMovie = movies.first?.id }
}
}
Kluczowe elementy: @FocusState — śledzenie bieżącego fokusu; .focusable() — czyni element dostępnym dla fokusu; .scaleEffect() — animacja powiększenia przy fokusie, ważna dla wizualnego sprzężenia zwrotnego na TV.
Analogiczny przykład dla Android TV z Leanback Library w Kotlin:
// MainActivity.kt
class MainActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
class MainFragment : BrowseSupportFragment() {
private val moviePresenter = MoviePresenter()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
title = getString(R.string.app_name)
headersState = HEADERS_ENABLED
setupAdapter()
}
private fun setupAdapter() {
val rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
val listRowAdapter = ArrayObjectAdapter(moviePresenter)
listRowAdapter.add(Movie("Inception", "2010", R.drawable.poster_1))
listRowAdapter.add(Movie("Interstellar", "2014", R.drawable.poster_2))
rowsAdapter.add(ListRow(HeaderItem(0, "Movies"), listRowAdapter))
adapter = rowsAdapter
}
}
data class Movie(val title: String, val subtitle: String, val imageResId: Int)
class MoviePresenter : Presenter() {
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
val cardView = ImageCardView(parent.context).apply {
isFocusable = true
setMainImageDimensions(200, 300)
}
return ViewHolder(cardView)
}
override fun onBindViewHolder(viewHolder: ViewHolder, item: Any) {
val movie = item as Movie
(viewHolder.view as ImageCardView).apply {
titleText = movie.title
contentText = movie.subtitle
}
}
override fun onUnbindViewHolder(viewHolder: ViewHolder) {}
}
Kluczowe elementy: BrowseSupportFragment — główny fragment Leanback z nagłówkami; Presenter — abstrakcja do tworzenia ViewHolder, analogiczna do RecyclerView.Adapter; ImageCardView — standardowa karta z obrazem, tytułem i podtytułem; isFocusable = true — obowiązkowy atrybut dla elementów TV.
Często zadawane pytania
TV App jest sterowana pilotem (D-pad) zamiast dotyku, używa Focus Engine do nawigacji, jest zoptymalizowana pod duży ekran (Full HD lub 4K) i nie ma ograniczeń baterii. Wszystkie elementy muszą być dostępne poprzez kierunkowe przesuwanie fokusu.
Focus Engine — system na tvOS, automatycznie określający aktywny element interfejsu. Po naciśnięciu przycisku D-pad system analizuje położenie focusable-elementów, oblicza najbliższego kandydata i płynnie przenosi na niego fokus z animacją.
Główny framework — Leanback Library (BrowseFragment, DetailsFragment, PlaybackOverlayFragment). Dla nowoczesnych projektów dostępny jest również Jetpack Compose for TV z eksperymentalnym wsparciem.
Do początkowej fazy tworzenia wystarczą symulatory: Xcode zawiera symulator tvOS z Siri Remote, Android Studio — emulator Android TV. Do końcowego testowania zaleca się urządzenie fizyczne.
Apple TV App publikuje się przez App Store Connect za pomocą Xcode Organizer. Android TV App — przez Google Play Console z określeniem LEANBACK_LAUNCHER w manifeście i zrzutami ekranu 1920x1080.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również