Improve edge-to-edge even more

Eliminate a stupid third-party library and fix an elevation issue with QueueFragment as well.
This commit is contained in:
OxygenCobalt 2020-12-02 15:26:48 -07:00
parent 0079f41776
commit 63630aa42e
10 changed files with 94 additions and 57 deletions

View file

@ -97,9 +97,6 @@ dependencies {
// Dialogs // Dialogs
implementation 'com.afollestad.material-dialogs:core:3.3.0' implementation 'com.afollestad.material-dialogs:core:3.3.0'
// Edge-To-Edge insets
implementation "dev.chrisbanes:insetter-ktx:0.3.1"
// --- DEV --- // --- DEV ---
// Lint // Lint

View file

@ -7,12 +7,14 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.view.WindowInsets import android.view.WindowInsets
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
import org.oxycblt.auxio.databinding.ActivityMainBinding import org.oxycblt.auxio.databinding.ActivityMainBinding
import org.oxycblt.auxio.playback.PlaybackService import org.oxycblt.auxio.playback.PlaybackService
import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.settings.SettingsViewModel
import org.oxycblt.auxio.ui.accent import org.oxycblt.auxio.ui.accent
import org.oxycblt.auxio.ui.handleTransparentSystemBars import org.oxycblt.auxio.ui.handleTransparentSystemBars
import org.oxycblt.auxio.ui.toColor import org.oxycblt.auxio.ui.toColor
@ -22,11 +24,14 @@ import org.oxycblt.auxio.ui.toColor
// TODO: Landscape UI layouts // TODO: Landscape UI layouts
// FIXME: Compat issue with Versions 5 that leads to progress bar looking off // FIXME: Compat issue with Versions 5 that leads to progress bar looking off
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private val settingsModel: SettingsViewModel by viewModels()
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// --- UI SETUP ---
val binding = DataBindingUtil.setContentView<ActivityMainBinding>( val binding = DataBindingUtil.setContentView<ActivityMainBinding>(
this, R.layout.activity_main this, R.layout.activity_main
) )
@ -42,35 +47,33 @@ class MainActivity : AppCompatActivity() {
// Apply the theme // Apply the theme
setTheme(accent.second) setTheme(accent.second)
// If enabled and possible, go through a stupidly long & complicated process
// just to get edge-to-edge to work.
// TODO: Make the navigation bar fully transparent
if (settingsManager.getEdgeToEdge() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { if (settingsManager.getEdgeToEdge() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
window?.apply { doEdgeToEdgeSetup(binding)
statusBarColor = Color.TRANSPARENT }
navigationBarColor = R.color.nav_color.toColor(this@MainActivity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // --- VIEWMODEL SETUP ---
Log.d(this::class.simpleName, "Doing R+ edge-to-edge.")
setDecorFitsSystemWindows(false) settingsModel.theme.observe(this) {
if (it != null) {
doThemeRecreate(it)
binding.root.setOnApplyWindowInsetsListener { _, insets -> settingsModel.doneWithThemeUpdate()
WindowInsets.Builder() }
.setInsets( }
WindowInsets.Type.systemBars(),
insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
)
.build()
}
} else {
Log.d(this::class.simpleName, "Doing legacy edge-to-edge.")
binding.root.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or settingsModel.accent.observe(this) {
View.SYSTEM_UI_FLAG_LAYOUT_STABLE if (it != null) {
} recreate()
handleTransparentSystemBars(resources.configuration) settingsModel.doneWithAccentUpdate()
}
}
settingsModel.edge.observe(this) {
if (it != null) {
recreate()
settingsModel.doneWithEdgeUpdate()
} }
} }
} }
@ -83,6 +86,43 @@ class MainActivity : AppCompatActivity() {
} }
} }
private fun doEdgeToEdgeSetup(binding: ActivityMainBinding) {
window?.apply {
statusBarColor = Color.TRANSPARENT
// Use a heavily transparent scrim on the nav bar as otherwise the transparency wont
// work.
navigationBarColor = R.color.nav_color.toColor(this@MainActivity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Do modern edge to edge [Which is really a shot in the dark tbh]
Log.d(this::class.simpleName, "Doing R+ edge-to-edge.")
setDecorFitsSystemWindows(false)
binding.root.setOnApplyWindowInsetsListener { _, insets ->
WindowInsets.Builder()
.setInsets(
WindowInsets.Type.systemBars(),
insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
)
.build()
}
} else {
// Do old edge-to-edge otherwise
Log.d(this::class.simpleName, "Doing legacy edge-to-edge.")
binding.root.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
handleTransparentSystemBars(resources.configuration)
}
}
/**
*
*/
fun doThemeRecreate(newTheme: Int) { fun doThemeRecreate(newTheme: Int) {
AppCompatDelegate.setDefaultNightMode(newTheme) AppCompatDelegate.setDefaultNightMode(newTheme)
} }

View file

@ -120,6 +120,7 @@ class MainFragment : Fragment() {
return binding.root return binding.root
} }
// Functions that check if MainFragment should nav over to LibraryFragment, or whether // Functions that check if MainFragment should nav over to LibraryFragment, or whether
// it should stay put. Mostly by checking if the navController is currently in a detail // it should stay put. Mostly by checking if the navController is currently in a detail
// fragment, and if the playing item is already being shown. // fragment, and if the playing item is already being shown.

View file

@ -4,12 +4,12 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import dev.chrisbanes.insetter.applySystemWindowInsetsToMargin import com.afollestad.materialdialogs.utils.MDUtil.updatePadding
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentQueueBinding import org.oxycblt.auxio.databinding.FragmentQueueBinding
import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.BaseModel
@ -44,8 +44,18 @@ class QueueFragment : Fragment() {
// --- UI SETUP --- // --- UI SETUP ---
binding.queueToolbar.setNavigationOnClickListener { binding.queueToolbar.apply {
findNavController().navigateUp() setNavigationOnClickListener {
findNavController().navigateUp()
}
setOnApplyWindowInsetsListener { v, insets ->
(parent as View).updatePadding(
top = insets.systemWindowInsetTop
)
insets
}
} }
binding.queueRecycler.apply { binding.queueRecycler.apply {
@ -77,12 +87,6 @@ class QueueFragment : Fragment() {
return binding.root return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Toolbar>(R.id.queue_toolbar).applySystemWindowInsetsToMargin(top = true)
}
private fun createQueueData(): MutableList<BaseModel> { private fun createQueueData(): MutableList<BaseModel> {
val queue = mutableListOf<BaseModel>() val queue = mutableListOf<BaseModel>()

View file

@ -11,7 +11,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView import com.afollestad.materialdialogs.customview.customView
import org.oxycblt.auxio.MainActivity
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.settings.adapters.AccentAdapter import org.oxycblt.auxio.settings.adapters.AccentAdapter
import org.oxycblt.auxio.ui.ACCENTS import org.oxycblt.auxio.ui.ACCENTS
@ -60,28 +59,12 @@ class SettingsListFragment : PreferenceFragmentCompat() {
else -> R.drawable.ic_auto else -> R.drawable.ic_auto
} }
) )
(requireActivity() as MainActivity).doThemeRecreate(it)
settingsModel.doneWithThemeUpdate()
} }
} }
settingsModel.accent.observe(viewLifecycleOwner) { settingsModel.accent.observe(viewLifecycleOwner) {
if (it != null) { if (it != null) {
accentPref?.summary = getDetailedAccentSummary(requireActivity(), it) accentPref?.summary = getDetailedAccentSummary(requireActivity(), it)
requireActivity().recreate()
settingsModel.doneWithAccentUpdate()
}
}
settingsModel.edge.observe(viewLifecycleOwner) {
if (it != null) {
requireActivity().recreate()
settingsModel.doneWithEdgeUpdate()
} }
} }

View file

@ -9,9 +9,6 @@ import org.oxycblt.auxio.ui.ACCENTS
/** /**
* Wrapper around the [SharedPreferences] class that writes & reads values without a context. * Wrapper around the [SharedPreferences] class that writes & reads values without a context.
*
* **Note:** Run any getter in a IO coroutine if possible, as SharedPrefs will read from disk
* the first time it occurs.
* @author OxygenCobalt * @author OxygenCobalt
*/ */
class SettingsManager private constructor(context: Context) : class SettingsManager private constructor(context: Context) :

View file

@ -4,6 +4,12 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
/**
* A [ViewModel] that provides a better interface for observing settings updates compared to
* [SettingsManager.Callback] or the default SharedPreferences listener.
* // TODO: Roll values & updates into this viewmodel
* @author OxygenCobalt
*/
class SettingsViewModel : ViewModel(), SettingsManager.Callback { class SettingsViewModel : ViewModel(), SettingsManager.Callback {
private val mTheme = MutableLiveData<Int?>() private val mTheme = MutableLiveData<Int?>()
val theme: LiveData<Int?> get() = mTheme val theme: LiveData<Int?> get() = mTheme

View file

@ -73,7 +73,7 @@ fun Spanned.render(): Spanned {
} }
/** /**
* Handle transparent system bars on light mode. Adapted from Music Player GO * Handle the new transparent system bars on light mode. Adapted from Music Player GO
* (https://github.com/enricocid/Music-Player-GO) * (https://github.com/enricocid/Music-Player-GO)
*/ */
@TargetApi(Build.VERSION_CODES.O_MR1) @TargetApi(Build.VERSION_CODES.O_MR1)

View file

@ -100,11 +100,18 @@ fun resolveAttr(context: Context, @AttrRes attr: Int): Int {
return color.toColor(context) return color.toColor(context)
} }
/**
* Get the name of an accent.
* TODO: Make these use translatable string resources!!!!
*/
fun getAccentItemSummary(context: Context, newAccent: Pair<Int, Int>): String { fun getAccentItemSummary(context: Context, newAccent: Pair<Int, Int>): String {
return context.resources.getResourceEntryName(newAccent.first) return context.resources.getResourceEntryName(newAccent.first)
.replace("_", " ").capitalize(Locale.getDefault()) .replace("_", " ").capitalize(Locale.getDefault())
} }
/**
* Get the name [in bold]] and the hex value of a theme.
*/
fun getDetailedAccentSummary(context: Context, newAccent: Pair<Int, Int>): Spanned { fun getDetailedAccentSummary(context: Context, newAccent: Pair<Int, Int>): Spanned {
val name = getAccentItemSummary(context, newAccent) val name = getAccentItemSummary(context, newAccent)
val hex = context.getString(accent.first).toUpperCase(Locale.getDefault()) val hex = context.getString(accent.first).toUpperCase(Locale.getDefault())

View file

@ -87,9 +87,11 @@
<item name="android:textSize">18sp</item> <item name="android:textSize">18sp</item>
</style> </style>
<!--
<style name="Theme.BottomSheetFix" parent="@style/Theme.Design.BottomSheetDialog"> <style name="Theme.BottomSheetFix" parent="@style/Theme.Design.BottomSheetDialog">
<item name="android:windowIsFloating">false</item> <item name="android:windowIsFloating">false</item>
<item name="android:navigationBarColor">@color/background</item> <item name="android:navigationBarColor">@color/background</item>
<item name="android:statusBarColor">@android:color/transparent</item> <item name="android:statusBarColor">@android:color/transparent</item>
</style> </style>
-->
</resources> </resources>