From dad709f5df845a7e0daa25b7d3dc2e617a1cfc93 Mon Sep 17 00:00:00 2001 From: Michatec Date: Mon, 30 Mar 2026 11:06:41 +0200 Subject: [PATCH] feat(ui): implement edge-to-edge support and improve splash transition - Enable edge-to-edge display in `MainActivity` and handle window insets in `PlayerFragment`. - Add a fade-out animation when hiding the loading overlay. - Sync player state with the controller during setup and reset playing state in preferences on service destruction. - Simplify splash screen drawable and update background color attributes in layout. - Remove manual navigation bar color overrides. --- .../java/com/michatec/radio/MainActivity.kt | 24 +++++++++++++++---- .../java/com/michatec/radio/PlayerFragment.kt | 17 +++++++++++-- .../java/com/michatec/radio/PlayerService.kt | 3 ++- .../com/michatec/radio/SettingsFragment.kt | 2 -- app/src/main/res/drawable/splash_screen.xml | 7 ++---- app/src/main/res/layout/activity_main.xml | 1 + 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/michatec/radio/MainActivity.kt b/app/src/main/java/com/michatec/radio/MainActivity.kt index 29f6b1a..43e051e 100644 --- a/app/src/main/java/com/michatec/radio/MainActivity.kt +++ b/app/src/main/java/com/michatec/radio/MainActivity.kt @@ -6,8 +6,10 @@ import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.View +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar +import androidx.core.view.isVisible import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.NavigationUI @@ -28,6 +30,7 @@ class MainActivity : AppCompatActivity() { /* Overrides onCreate from AppCompatActivity */ override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() setTheme(R.style.AppTheme) super.onCreate(savedInstanceState) @@ -49,19 +52,31 @@ class MainActivity : AppCompatActivity() { NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration) supportActionBar?.hide() - // TV-specific loading logic + // TV-specific loading logic: Hide the overlay once the app is ready if (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { Handler(Looper.getMainLooper()).postDelayed({ - findViewById(R.id.loading_layout)?.visibility = View.GONE - }, 1500) + hideLoadingOverlay() + }, 1200) } else { - findViewById(R.id.loading_layout)?.visibility = View.GONE + hideLoadingOverlay() } // register listener for changes in shared preferences PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener) } + /* Hides the loading/splash overlay */ + private fun hideLoadingOverlay() { + findViewById(R.id.loading_layout)?.let { overlay -> + if (overlay.isVisible) { + overlay.animate() + .alpha(0f) + .setDuration(500) + .withEndAction { overlay.visibility = View.GONE } + } + } + } + /* Overrides onResume from AppCompatActivity */ override fun onResume() { @@ -75,7 +90,6 @@ class MainActivity : AppCompatActivity() { /* Overrides onSupportNavigateUp from AppCompatActivity */ override fun onSupportNavigateUp(): Boolean { - // Taken from: https://developer.android.com/guide/navigation/navigation-ui#action_bar val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_host_container) as NavHostFragment val navController = navHostFragment.navController return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() diff --git a/app/src/main/java/com/michatec/radio/PlayerFragment.kt b/app/src/main/java/com/michatec/radio/PlayerFragment.kt index 00ac537..708cf8b 100644 --- a/app/src/main/java/com/michatec/radio/PlayerFragment.kt +++ b/app/src/main/java/com/michatec/radio/PlayerFragment.kt @@ -22,6 +22,9 @@ import androidx.annotation.OptIn import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.net.toUri +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.media3.common.MediaItem @@ -167,8 +170,11 @@ class PlayerFragment : Fragment(), // hide action bar (activity as AppCompatActivity).supportActionBar?.hide() - // set the same background color of the player sheet for the navigation bar - requireActivity().window.navigationBarColor = ContextCompat.getColor(requireActivity(), R.color.player_sheet_background) + ViewCompat.setOnApplyWindowInsetsListener(layout.rootView) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updatePadding(bottom = systemBars.bottom) + insets + } // associate the ItemTouchHelper with the RecyclerView itemTouchHelper = ItemTouchHelper(ItemTouchHelperCallback()) itemTouchHelper?.attachToRecyclerView(layout.recyclerView) @@ -405,6 +411,13 @@ class PlayerFragment : Fragment(), private fun setupController() { val controller: MediaController = this.controller ?: return controller.addListener(playerListener) + + // Sync local playerState with actual controller state + if (playerState.isPlaying != controller.isPlaying) { + playerState.isPlaying = controller.isPlaying + updatePlayerViews() + } + requestMetadataUpdate() // handle start intent handleStartIntent() diff --git a/app/src/main/java/com/michatec/radio/PlayerService.kt b/app/src/main/java/com/michatec/radio/PlayerService.kt index 9c12cae..44a6e5a 100644 --- a/app/src/main/java/com/michatec/radio/PlayerService.kt +++ b/app/src/main/java/com/michatec/radio/PlayerService.kt @@ -81,7 +81,8 @@ class PlayerService : MediaLibraryService() { /* Overrides onDestroy from Service */ override fun onDestroy() { - // player.removeAnalyticsListener(analyticsListener) + // Reset playing state in preferences + PreferencesHelper.saveIsPlaying(false) player.removeListener(playerListener) player.release() mediaLibrarySession.release() diff --git a/app/src/main/java/com/michatec/radio/SettingsFragment.kt b/app/src/main/java/com/michatec/radio/SettingsFragment.kt index 7d58173..8ba9674 100644 --- a/app/src/main/java/com/michatec/radio/SettingsFragment.kt +++ b/app/src/main/java/com/michatec/radio/SettingsFragment.kt @@ -21,7 +21,6 @@ import com.michatec.radio.dialogs.ErrorDialog import com.michatec.radio.dialogs.ThemeSelectionDialog import com.michatec.radio.dialogs.YesNoDialog import com.michatec.radio.helpers.* -import com.michatec.radio.helpers.AppThemeHelper.getColor import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch @@ -46,7 +45,6 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList (activity as AppCompatActivity).supportActionBar?.show() (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) (activity as AppCompatActivity).supportActionBar?.title = getString(R.string.fragment_settings_title) - requireActivity().window.navigationBarColor = getColor(requireContext(), android.R.attr.colorBackground) } /* Overrides onCreatePreferences from PreferenceFragmentCompat */ diff --git a/app/src/main/res/drawable/splash_screen.xml b/app/src/main/res/drawable/splash_screen.xml index 109f5b6..6bc5a9b 100644 --- a/app/src/main/res/drawable/splash_screen.xml +++ b/app/src/main/res/drawable/splash_screen.xml @@ -4,9 +4,6 @@ - - + android:gravity="center" + android:drawable="@mipmap/ic_launcher" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 90ef118..e0b890a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="?android:attr/colorBackground" android:fitsSystemWindows="true" tools:context=".MainActivity">