From fcebfda406943df62a861049a3943e0d2c901ee7 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Mon, 14 Dec 2020 19:38:46 -0700 Subject: [PATCH] Fix edge-to-edge bug in landscape Fix a bug where the drag handles in QueueFragment would be covered up by the navigation bar in edge-to-edge + landscape mode. --- app/build.gradle | 6 +-- .../java/org/oxycblt/auxio/MainActivity.kt | 2 + .../auxio/database/PlaybackStateDatabase.kt | 3 -- .../auxio/detail/AlbumDetailFragment.kt | 2 - .../auxio/detail/ArtistDetailFragment.kt | 2 - .../auxio/detail/GenreDetailFragment.kt | 2 - .../auxio/music/processing/MusicLoader.kt | 1 - .../auxio/playback/PlaybackFragment.kt | 3 +- .../auxio/playback/queue/QueueFragment.kt | 36 +++++++++----- .../org/oxycblt/auxio/ui/InterfaceUtils.kt | 48 +++++++++++++++++++ .../res/layout-land/fragment_playback.xml | 5 +- app/src/main/res/layout/fragment_playback.xml | 4 +- 12 files changed, 84 insertions(+), 30 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5ee63557f..e899774c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -69,12 +69,12 @@ dependencies { implementation 'androidx.viewpager2:viewpager2:1.0.0' // Navigation - def navigation_version = "2.3.1" + def navigation_version = "2.3.2" implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version" implementation "androidx.navigation:navigation-ui-ktx:$navigation_version" // Media - implementation 'androidx.media:media:1.2.0' + implementation 'androidx.media:media:1.2.1' // Preferences implementation 'androidx.preference:preference-ktx:1.1.1' @@ -104,7 +104,7 @@ dependencies { ktlint "com.pinterest:ktlint:0.37.2" // Memory Leak checking - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5' } task ktlint(type: JavaExec, group: "verification") { diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index fd4d28bd7..0f80f898e 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -53,6 +53,8 @@ class MainActivity : AppCompatActivity() { @Suppress("DEPRECATION") private fun doEdgeToEdgeSetup(binding: ActivityMainBinding) { + // TODO: Add landscape edge-to-edge support + window?.apply { statusBarColor = Color.TRANSPARENT diff --git a/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt b/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt index ae0505525..bf0a15528 100644 --- a/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/database/PlaybackStateDatabase.kt @@ -111,7 +111,6 @@ class PlaybackStateDatabase(context: Context) : /** * Read the stored [PlaybackState] from the database, if there is one. * @return The stored [PlaybackState], null if there isn't one,. - * @author OxygenCobalt */ fun readState(): PlaybackState? { val database = writableDatabase @@ -163,7 +162,6 @@ class PlaybackStateDatabase(context: Context) : /** * Write a list of [QueueItem]s to the database, clearing the previous queue present. * @param queue The list of [QueueItem]s to be written. - * @author OxygenCobalt */ fun writeQueue(queue: List) { val database = readableDatabase @@ -218,7 +216,6 @@ class PlaybackStateDatabase(context: Context) : /** * Read the database for any [QueueItem]s. * @return A list of any stored [QueueItem]s. - * @author OxygenCobalt */ fun readQueue(): List { val database = readableDatabase diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 9990a4b1c..d84ccaf7a 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -8,7 +8,6 @@ import androidx.appcompat.widget.PopupMenu import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import androidx.recyclerview.widget.GridLayoutManager import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding import org.oxycblt.auxio.detail.adapters.AlbumSongAdapter @@ -20,7 +19,6 @@ import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.state.PlaybackMode import org.oxycblt.auxio.ui.createToast import org.oxycblt.auxio.ui.disable -import org.oxycblt.auxio.ui.isLandscape import org.oxycblt.auxio.ui.setupAlbumSongActions /** diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index bef92f5ed..274637e91 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -8,7 +8,6 @@ import androidx.appcompat.widget.PopupMenu import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import androidx.recyclerview.widget.GridLayoutManager import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding import org.oxycblt.auxio.detail.adapters.ArtistAlbumAdapter @@ -17,7 +16,6 @@ import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.disable -import org.oxycblt.auxio.ui.isLandscape import org.oxycblt.auxio.ui.setupAlbumActions /** diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index 036a92ea8..db3ab6518 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -8,7 +8,6 @@ import androidx.appcompat.widget.PopupMenu import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import androidx.recyclerview.widget.GridLayoutManager import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentGenreDetailBinding import org.oxycblt.auxio.detail.adapters.GenreArtistAdapter @@ -16,7 +15,6 @@ import org.oxycblt.auxio.logD import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.disable -import org.oxycblt.auxio.ui.isLandscape import org.oxycblt.auxio.ui.setupArtistActions /** diff --git a/app/src/main/java/org/oxycblt/auxio/music/processing/MusicLoader.kt b/app/src/main/java/org/oxycblt/auxio/music/processing/MusicLoader.kt index f733eed0e..c511a3719 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/processing/MusicLoader.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/processing/MusicLoader.kt @@ -144,7 +144,6 @@ class MusicLoader( }.toMutableList() // Then try to associate any genres with their respective artists. - // TODO: This is already querying all genre songs, just move it. for (genre in genres) { val artistGenreCursor = resolver.query( Genres.Members.getContentUri("external", genre.id), diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt index cd8a4a6eb..161e9a68e 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt @@ -84,7 +84,8 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener { } // Make ellipsizing of song title work - binding.playbackSong.isSelected = true + // Disabled until I can figure out why marquee causes a memory leak. + // binding.playbackSong.isSelected = true binding.playbackSeekBar.setOnSeekBarChangeListener(this) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index bd3a0f32e..bc636235d 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -17,6 +17,9 @@ import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.state.PlaybackMode +import org.oxycblt.auxio.settings.SettingsManager +import org.oxycblt.auxio.ui.isLandscape +import org.oxycblt.auxio.ui.isSystemBarOnBottom /** * A [Fragment] that contains both the user queue and the next queue, with the ability to @@ -35,6 +38,7 @@ class QueueFragment : Fragment() { ): View { val binding = FragmentQueueBinding.inflate(inflater) + val settingsManager = SettingsManager.getInstance() val callback = QueueDragCallback(playbackModel) val helper = ItemTouchHelper(callback) val queueAdapter = QueueAdapter(helper) { @@ -45,6 +49,14 @@ class QueueFragment : Fragment() { // --- UI SETUP --- + // Band-aid that fixes a bug with landscape edge-to-edge where the queue drag buttons + // will be behind the status bar. + if (settingsManager.edgeEnabled) { + if (isLandscape(resources) && !isSystemBarOnBottom(requireActivity())) { + binding.root.rootView.fitsSystemWindows = true + } + } + binding.queueToolbar.apply { setNavigationOnClickListener { findNavController().navigateUp() @@ -53,18 +65,20 @@ class QueueFragment : Fragment() { // Since QueueFragment doesn't fit system windows, inset padding needs to be // artificially applied to the Toolbar so that it fits on the main window AND // so that the elevation doesn't show on the top. - setOnApplyWindowInsetsListener @Suppress("DEPRECATION") { _, insets -> - val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - insets.getInsets(WindowInsets.Type.systemBars()).top - } else { - insets.systemWindowInsetTop + if (!binding.root.rootView.fitsSystemWindows) { + setOnApplyWindowInsetsListener @Suppress("DEPRECATION") { _, insets -> + val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + insets.getInsets(WindowInsets.Type.systemBars()).top + } else { + insets.systemWindowInsetTop + } + + (parent as View).updatePadding( + top = top + ) + + insets } - - (parent as View).updatePadding( - top = top - ) - - insets } } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt index 721a905d2..c1028a744 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt @@ -1,18 +1,22 @@ package org.oxycblt.auxio.ui import android.annotation.TargetApi +import android.app.Activity import android.content.Context import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.Resources +import android.graphics.Point import android.os.Build import android.text.SpannableString import android.text.Spanned import android.text.style.ForegroundColorSpan +import android.util.DisplayMetrics import android.view.MenuItem import android.view.View import android.view.Window import android.view.WindowInsetsController +import android.view.WindowManager import android.widget.ImageButton import android.widget.Toast import androidx.annotation.ColorInt @@ -31,6 +35,13 @@ import org.oxycblt.auxio.settings.SettingsManager // Functions for managing UI elements [Not Colors] +object InterfaceUtils { + const val NAV_HIDDEN = -1 + const val NAV_ON_LEFT = 0 + const val NAV_ON_RIGHT = 1 + const val NAV_ON_BOTTOM = 2 +} + /** * Apply a text color to a [MenuItem] * @param color The text color that should be applied. @@ -81,6 +92,43 @@ fun Spanned.render(): Spanned { ) } +/** + * Check if the system bars are on the bottom. + * @return If the system bars are on the bottom, false if no. + */ +@Suppress("DEPRECATION") +fun isSystemBarOnBottom(activity: Activity): Boolean { + val realPoint = Point() + val metrics = DisplayMetrics() + + var width = 0 + var height = 0 + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + activity.display?.let { display -> + display.getRealSize(realPoint) + + activity.windowManager.currentWindowMetrics.bounds.also { + width = it.width() + height = it.height() + } + } + } else { + (activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager).apply { + defaultDisplay.getRealSize(realPoint) + defaultDisplay.getMetrics(metrics) + + width = metrics.widthPixels + height = metrics.heightPixels + } + } + + val config = activity.resources.configuration + val canMove = (width != height && config.smallestScreenWidthDp < 600) + + return (!canMove || width < height) +} + /** * Handle transparent system bars. Adapted from Music Player GO * (https://github.com/enricocid/Music-Player-GO) diff --git a/app/src/main/res/layout-land/fragment_playback.xml b/app/src/main/res/layout-land/fragment_playback.xml index a4fee3c96..c56da987e 100644 --- a/app/src/main/res/layout-land/fragment_playback.xml +++ b/app/src/main/res/layout-land/fragment_playback.xml @@ -53,15 +53,16 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margin_mid_large" - android:ellipsize="marquee" + android:layout_marginEnd="24dp" + android:ellipsize="end" android:focusable="true" android:fontFamily="@font/inter_semibold" - android:marqueeRepeatLimit="marquee_forever" android:onClick="@{() -> playbackModel.navToItem(playbackModel.song)}" android:singleLine="true" android:text="@{song.name}" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" app:layout_constraintBottom_toTopOf="@+id/playback_artist" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/playback_cover" app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" app:layout_constraintVertical_chainStyle="packed" diff --git a/app/src/main/res/layout/fragment_playback.xml b/app/src/main/res/layout/fragment_playback.xml index 93dd2976c..e337ee528 100644 --- a/app/src/main/res/layout/fragment_playback.xml +++ b/app/src/main/res/layout/fragment_playback.xml @@ -56,10 +56,8 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/margin_mid_large" android:layout_marginEnd="@dimen/margin_mid_large" - android:ellipsize="marquee" - android:focusable="true" + android:ellipsize="end" android:fontFamily="@font/inter_semibold" - android:marqueeRepeatLimit="marquee_forever" android:onClick="@{() -> playbackModel.navToItem(playbackModel.song)}" android:singleLine="true" android:text="@{song.name}"