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.
This commit is contained in:
OxygenCobalt 2020-12-14 19:38:46 -07:00
parent 28b6edb5d6
commit fcebfda406
12 changed files with 84 additions and 30 deletions

View file

@ -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") {

View file

@ -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

View file

@ -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<QueueItem>) {
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<QueueItem> {
val database = readableDatabase

View file

@ -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
/**

View file

@ -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
/**

View file

@ -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
/**

View file

@ -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),

View file

@ -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)

View file

@ -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
}
}

View file

@ -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)

View file

@ -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"

View file

@ -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}"