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:
parent
0079f41776
commit
63630aa42e
10 changed files with 94 additions and 57 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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>()
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) :
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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>
|
Loading…
Reference in a new issue