Heavily refactor navigation
Make how navigation to the detail fragments much simpler/easier to maintain compared to previously.
This commit is contained in:
parent
fafaa0bf1f
commit
60af5f8656
15 changed files with 143 additions and 120 deletions
|
@ -14,8 +14,6 @@ import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import org.oxycblt.auxio.databinding.FragmentMainBinding
|
import org.oxycblt.auxio.databinding.FragmentMainBinding
|
||||||
import org.oxycblt.auxio.detail.DetailViewModel
|
import org.oxycblt.auxio.detail.DetailViewModel
|
||||||
import org.oxycblt.auxio.music.Album
|
|
||||||
import org.oxycblt.auxio.music.Artist
|
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
|
@ -95,12 +93,10 @@ class MainFragment : Fragment() {
|
||||||
if (it != null && navController != null) {
|
if (it != null && navController != null) {
|
||||||
val curDest = navController.currentDestination?.id
|
val curDest = navController.currentDestination?.id
|
||||||
|
|
||||||
val isOk = when (it) {
|
var isOk = false
|
||||||
is Song -> (detailModel.currentAlbum.value?.id == it.album.id) magic (curDest != R.id.album_detail_fragment)
|
|
||||||
is Album -> (detailModel.currentAlbum.value?.id == it.id) magic (curDest != R.id.album_detail_fragment)
|
|
||||||
is Artist -> (detailModel.currentArtist.value?.id == it.id) magic (curDest != R.id.artist_detail_fragment)
|
|
||||||
|
|
||||||
else -> false
|
if (curDest == R.id.songs_fragment || curDest == R.id.settings_fragment) {
|
||||||
|
isOk = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOk) {
|
if (isOk) {
|
||||||
|
@ -116,17 +112,6 @@ class MainFragment : Fragment() {
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Magic boolean logic that gets navigation working.
|
|
||||||
* true true -> true |
|
|
||||||
* true false -> false |
|
|
||||||
* false true -> true |
|
|
||||||
* false false -> false |
|
|
||||||
*/
|
|
||||||
private infix fun Boolean.magic(other: Boolean): Boolean {
|
|
||||||
return if (!this && !other) false else !(this && !other)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom navigator code that has proper animations, unlike BottomNavigationView.setupWithNavController().
|
* Custom navigator code that has proper animations, unlike BottomNavigationView.setupWithNavController().
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.detail.adapters.AlbumDetailAdapter
|
import org.oxycblt.auxio.detail.adapters.AlbumDetailAdapter
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
|
@ -82,28 +83,41 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
detailAdapter.submitList(data)
|
detailAdapter.submitList(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
detailModel.doneWithNavToParent()
|
|
||||||
|
|
||||||
detailModel.navToParent.observe(viewLifecycleOwner) {
|
|
||||||
if (it) {
|
|
||||||
findNavController().navigate(
|
|
||||||
AlbumDetailFragmentDirections.actionShowParentArtist(
|
|
||||||
detailModel.currentAlbum.value!!.artist.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
detailModel.doneWithNavToParent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
detailModel.navToItem.observe(viewLifecycleOwner) {
|
detailModel.navToItem.observe(viewLifecycleOwner) {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
if (it is Song) {
|
logD(it.name)
|
||||||
scrollToPlayingItem()
|
when (it) {
|
||||||
}
|
is Song -> {
|
||||||
|
if (detailModel.currentAlbum.value!!.id == it.album.id) {
|
||||||
|
scrollToItem(it.id)
|
||||||
|
|
||||||
if (it is Album && it.id == detailModel.currentAlbum.value!!.id) {
|
detailModel.doneWithNavToItem()
|
||||||
detailModel.doneWithNavToItem()
|
} else {
|
||||||
|
findNavController().navigate(
|
||||||
|
AlbumDetailFragmentDirections.actionShowAlbum(it.album.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is Album -> {
|
||||||
|
if (detailModel.currentAlbum.value!!.id == it.id) {
|
||||||
|
binding.detailRecycler.scrollToPosition(0)
|
||||||
|
detailModel.doneWithNavToItem()
|
||||||
|
} else {
|
||||||
|
findNavController().navigate(
|
||||||
|
AlbumDetailFragmentDirections.actionShowAlbum(it.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is Artist -> {
|
||||||
|
logD("Hello?")
|
||||||
|
findNavController().navigate(
|
||||||
|
AlbumDetailFragmentDirections.actionShowArtist(it.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,14 +158,11 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun scrollToItem(id: Long) {
|
||||||
* Scroll to the currently playing item.
|
|
||||||
*/
|
|
||||||
private fun scrollToPlayingItem() {
|
|
||||||
// Calculate where the item for the currently played song is
|
// Calculate where the item for the currently played song is
|
||||||
val pos = detailModel.albumSortMode.value!!.getSortedSongList(
|
val pos = detailModel.albumSortMode.value!!.getSortedSongList(
|
||||||
detailModel.currentAlbum.value!!.songs
|
detailModel.currentAlbum.value!!.songs
|
||||||
).indexOf(playbackModel.song.value)
|
).indexOfFirst { it.id == id }
|
||||||
|
|
||||||
if (pos != -1) {
|
if (pos != -1) {
|
||||||
binding.detailRecycler.post {
|
binding.detailRecycler.post {
|
||||||
|
@ -167,8 +178,6 @@ class AlbumDetailFragment : DetailFragment() {
|
||||||
binding.detailAppbar.isLifted = true
|
binding.detailAppbar.isLifted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
detailModel.doneWithNavToItem()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Artist
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.ui.ActionMenu
|
import org.oxycblt.auxio.ui.ActionMenu
|
||||||
import org.oxycblt.auxio.ui.requireCompatActivity
|
import org.oxycblt.auxio.ui.requireCompatActivity
|
||||||
|
@ -77,8 +78,22 @@ class ArtistDetailFragment : DetailFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
detailModel.navToItem.observe(viewLifecycleOwner) {
|
detailModel.navToItem.observe(viewLifecycleOwner) {
|
||||||
if (it != null && it is Artist) {
|
if (it != null) {
|
||||||
detailModel.doneWithNavToItem()
|
if (it is Artist) {
|
||||||
|
if (it.id == detailModel.currentArtist.value!!.id) {
|
||||||
|
detailModel.doneWithNavToItem()
|
||||||
|
} else {
|
||||||
|
findNavController().navigate(
|
||||||
|
ArtistDetailFragmentDirections.actionShowArtist(it.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val albumId = if (it is Song) it.album.id else it.id
|
||||||
|
|
||||||
|
findNavController().navigate(
|
||||||
|
ArtistDetailFragmentDirections.actionShowAlbum(albumId)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.databinding.FragmentDetailBinding
|
import org.oxycblt.auxio.databinding.FragmentDetailBinding
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
|
import org.oxycblt.auxio.ui.fixAnimationInfoMemoryLeak
|
||||||
import org.oxycblt.auxio.ui.isLandscape
|
import org.oxycblt.auxio.ui.isLandscape
|
||||||
import org.oxycblt.auxio.ui.memberBinding
|
import org.oxycblt.auxio.ui.memberBinding
|
||||||
|
|
||||||
|
@ -44,6 +45,12 @@ abstract class DetailFragment : Fragment() {
|
||||||
callback.isEnabled = false
|
callback.isEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
|
||||||
|
fixAnimationInfoMemoryLeak()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut method for doing setup of the detail toolbar.
|
* Shortcut method for doing setup of the detail toolbar.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -36,16 +36,10 @@ class DetailViewModel : ViewModel() {
|
||||||
private val mCurrentAlbum = MutableLiveData<Album?>()
|
private val mCurrentAlbum = MutableLiveData<Album?>()
|
||||||
val currentAlbum: LiveData<Album?> get() = mCurrentAlbum
|
val currentAlbum: LiveData<Album?> get() = mCurrentAlbum
|
||||||
|
|
||||||
// Navigation flags
|
// Primary navigation flag.
|
||||||
private val mNavToItem = MutableLiveData<BaseModel?>()
|
private val mNavToItem = MutableLiveData<BaseModel?>()
|
||||||
val navToItem: LiveData<BaseModel?> get() = mNavToItem
|
val navToItem: LiveData<BaseModel?> get() = mNavToItem
|
||||||
|
|
||||||
private val mNavToParent = MutableLiveData<Boolean>()
|
|
||||||
val navToParent: LiveData<Boolean> get() = mNavToParent
|
|
||||||
|
|
||||||
private val mNavToChild = MutableLiveData<BaseModel?>()
|
|
||||||
val navToChild: LiveData<BaseModel?> get() = mNavToChild
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the current navigation status
|
* Update the current navigation status
|
||||||
* @param value Whether the current [DetailFragment] is navigating or not.
|
* @param value Whether the current [DetailFragment] is navigating or not.
|
||||||
|
@ -113,23 +107,4 @@ class DetailViewModel : ViewModel() {
|
||||||
fun doneWithNavToItem() {
|
fun doneWithNavToItem() {
|
||||||
mNavToItem.value = null
|
mNavToItem.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Mark that parent navigation should occur */
|
|
||||||
fun navToParent() {
|
|
||||||
mNavToParent.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Mark that the UI is done with the parent navigation */
|
|
||||||
fun doneWithNavToParent() {
|
|
||||||
mNavToParent.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Navigate to some child item (Primarily used by GenreDetailFragment) */
|
|
||||||
fun navToChild(child: BaseModel) {
|
|
||||||
mNavToChild.value = child
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doneWithNavToChild() {
|
|
||||||
mNavToChild.value = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Artist
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.ui.ActionMenu
|
import org.oxycblt.auxio.ui.ActionMenu
|
||||||
import org.oxycblt.auxio.ui.requireCompatActivity
|
import org.oxycblt.auxio.ui.requireCompatActivity
|
||||||
|
@ -69,19 +70,23 @@ class GenreDetailFragment : DetailFragment() {
|
||||||
detailAdapter.submitList(data)
|
detailAdapter.submitList(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
detailModel.navToChild.observe(viewLifecycleOwner) {
|
detailModel.navToItem.observe(viewLifecycleOwner) {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
if (it is Artist) {
|
when (it) {
|
||||||
findNavController().navigate(
|
is Artist -> findNavController().navigate(
|
||||||
GenreDetailFragmentDirections.actionGoArtist(it.id)
|
GenreDetailFragmentDirections.actionShowArtist(it.id)
|
||||||
)
|
)
|
||||||
} else if (it is Album) {
|
|
||||||
findNavController().navigate(
|
|
||||||
GenreDetailFragmentDirections.actionGoAlbum(it.id)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
detailModel.doneWithNavToChild()
|
is Album -> findNavController().navigate(
|
||||||
|
GenreDetailFragmentDirections.actionShowAlbum(it.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
is Song -> findNavController().navigate(
|
||||||
|
GenreDetailFragmentDirections.actionShowAlbum(it.album.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentSearchBinding
|
import org.oxycblt.auxio.databinding.FragmentSearchBinding
|
||||||
|
import org.oxycblt.auxio.detail.DetailViewModel
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.logE
|
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Artist
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
|
@ -26,6 +26,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
import org.oxycblt.auxio.ui.ActionMenu
|
import org.oxycblt.auxio.ui.ActionMenu
|
||||||
import org.oxycblt.auxio.ui.accent
|
import org.oxycblt.auxio.ui.accent
|
||||||
|
import org.oxycblt.auxio.ui.fixAnimationInfoMemoryLeak
|
||||||
import org.oxycblt.auxio.ui.getLandscapeSpans
|
import org.oxycblt.auxio.ui.getLandscapeSpans
|
||||||
import org.oxycblt.auxio.ui.isLandscape
|
import org.oxycblt.auxio.ui.isLandscape
|
||||||
import org.oxycblt.auxio.ui.requireCompatActivity
|
import org.oxycblt.auxio.ui.requireCompatActivity
|
||||||
|
@ -40,6 +41,7 @@ class SearchFragment : Fragment() {
|
||||||
// SearchViewModel only scoped to this Fragment
|
// SearchViewModel only scoped to this Fragment
|
||||||
private val searchModel: SearchViewModel by viewModels()
|
private val searchModel: SearchViewModel by viewModels()
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
|
private val detailModel: DetailViewModel by activityViewModels()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -113,25 +115,27 @@ class SearchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detailModel.navToItem.observe(viewLifecycleOwner) {
|
||||||
|
if (it != null) {
|
||||||
|
findNavController().navigate(
|
||||||
|
when (it) {
|
||||||
|
is Song -> SearchFragmentDirections.actionShowAlbum(it.album.id)
|
||||||
|
is Album -> SearchFragmentDirections.actionShowAlbum(it.id)
|
||||||
|
is Artist -> SearchFragmentDirections.actionShowArtist(it.id)
|
||||||
|
|
||||||
|
else -> return@observe
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|
||||||
try {
|
fixAnimationInfoMemoryLeak()
|
||||||
// Use reflection to fix a memory leak in the fragment source code that occurs
|
|
||||||
// from leaving an EditText focused when exiting the view.
|
|
||||||
// I cant believe I have to do this.
|
|
||||||
Fragment::class.java.getDeclaredMethod("setFocusedView", View::class.java).apply {
|
|
||||||
isAccessible = true
|
|
||||||
invoke(this@SearchFragment, null)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logE("Hacky reflection leak fix failed.")
|
|
||||||
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|
|
@ -137,13 +137,13 @@ class ActionMenu(
|
||||||
|
|
||||||
R.id.action_go_album -> {
|
R.id.action_go_album -> {
|
||||||
if (data is Song) {
|
if (data is Song) {
|
||||||
determineWhereToNavWithSong(data.album)
|
detailModel.navToItem(data.album)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_go_artist -> {
|
R.id.action_go_artist -> {
|
||||||
if (data is Song) {
|
if (data is Song) {
|
||||||
determineWhereToNavWithSong(data.album.artist)
|
detailModel.navToItem(data.album.artist)
|
||||||
} else if (data is Album) {
|
} else if (data is Album) {
|
||||||
detailModel.navToItem(data.artist)
|
detailModel.navToItem(data.artist)
|
||||||
}
|
}
|
||||||
|
@ -151,14 +151,6 @@ class ActionMenu(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun determineWhereToNavWithSong(parent: BaseModel) {
|
|
||||||
when (flag) {
|
|
||||||
FLAG_NONE -> detailModel.navToItem(parent)
|
|
||||||
FLAG_IN_ALBUM -> detailModel.navToParent()
|
|
||||||
FLAG_IN_GENRE -> detailModel.navToChild(parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** No Flags **/
|
/** No Flags **/
|
||||||
const val FLAG_NONE = -1
|
const val FLAG_NONE = -1
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.graphics.Point
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -20,6 +21,7 @@ import androidx.core.text.HtmlCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.logE
|
||||||
|
|
||||||
// --- VIEW CONFIGURATION ---
|
// --- VIEW CONFIGURATION ---
|
||||||
|
|
||||||
|
@ -139,6 +141,7 @@ fun Activity.isIrregularLandscape(): Boolean {
|
||||||
* Check if the system bars are on the bottom.
|
* Check if the system bars are on the bottom.
|
||||||
* @return If the system bars are on the bottom, false if no.
|
* @return If the system bars are on the bottom, false if no.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private fun isSystemBarOnBottom(activity: Activity): Boolean {
|
private fun isSystemBarOnBottom(activity: Activity): Boolean {
|
||||||
val realPoint = Point()
|
val realPoint = Point()
|
||||||
val metrics = DisplayMetrics()
|
val metrics = DisplayMetrics()
|
||||||
|
@ -170,3 +173,21 @@ private fun isSystemBarOnBottom(activity: Activity): Boolean {
|
||||||
|
|
||||||
return (!canMove || width < height)
|
return (!canMove || width < height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- HACKY NIGHTMARES ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use R E F L E C T I O N to fix a memory leak where mAnimationInfo will keep a reference to
|
||||||
|
* its focused view.
|
||||||
|
* I can't believe I have to do this.
|
||||||
|
*/
|
||||||
|
fun Fragment.fixAnimationInfoMemoryLeak() {
|
||||||
|
try {
|
||||||
|
Fragment::class.java.getDeclaredMethod("setFocusedView", View::class.java).let {
|
||||||
|
it.isAccessible = true
|
||||||
|
it.invoke(this, null)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logE("mAnimationInfo leak fix failed.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
android:id="@+id/playback_layout"
|
android:id="@+id/playback_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:animateLayoutChanges="true"
|
|
||||||
android:background="@color/background"
|
android:background="@color/background"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
android:background="@drawable/ui_ripple"
|
android:background="@drawable/ui_ripple"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:onClick="@{() -> detailModel.navToParent()}"
|
android:onClick="@{() -> detailModel.navToItem(album.artist)}"
|
||||||
android:text="@{album.artist.name}"
|
android:text="@{album.artist.name}"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
android:id="@+id/playback_layout"
|
android:id="@+id/playback_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:animateLayoutChanges="true"
|
|
||||||
android:background="@color/background"
|
android:background="@color/background"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
android:id="@+id/playback_layout"
|
android:id="@+id/playback_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:animateLayoutChanges="true"
|
|
||||||
android:background="@color/background"
|
android:background="@color/background"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/margin_medium"
|
android:layout_marginStart="@dimen/margin_medium"
|
||||||
android:onClick="@{() -> detailModel.navToParent()}"
|
android:onClick="@{() -> detailModel.navToItem(album.artist)}"
|
||||||
android:text="@{album.artist.name}"
|
android:text="@{album.artist.name}"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
|
|
@ -39,12 +39,18 @@
|
||||||
<argument
|
<argument
|
||||||
android:name="artistId"
|
android:name="artistId"
|
||||||
app:argType="long" />
|
app:argType="long" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_show_artist"
|
||||||
|
app:destination="@id/artist_detail_fragment"
|
||||||
|
app:enterAnim="@anim/nav_default_enter_anim"
|
||||||
|
app:exitAnim="@anim/nav_default_exit_anim"
|
||||||
|
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||||
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_show_album"
|
android:id="@+id/action_show_album"
|
||||||
app:destination="@id/album_detail_fragment"
|
app:destination="@id/album_detail_fragment"
|
||||||
app:enterAnim="@anim/nav_default_enter_anim"
|
app:enterAnim="@anim/nav_default_enter_anim"
|
||||||
app:exitAnim="@anim/nav_default_exit_anim"
|
app:exitAnim="@anim/nav_default_exit_anim"
|
||||||
app:launchSingleTop="true"
|
|
||||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
@ -57,12 +63,19 @@
|
||||||
android:name="albumId"
|
android:name="albumId"
|
||||||
app:argType="long" />
|
app:argType="long" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_show_parent_artist"
|
android:id="@+id/action_show_artist"
|
||||||
app:destination="@id/artist_detail_fragment"
|
app:destination="@id/artist_detail_fragment"
|
||||||
app:enterAnim="@anim/nav_default_enter_anim"
|
app:enterAnim="@anim/nav_default_enter_anim"
|
||||||
app:exitAnim="@anim/nav_default_exit_anim"
|
app:exitAnim="@anim/nav_default_exit_anim"
|
||||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_show_album"
|
||||||
|
app:destination="@id/album_detail_fragment"
|
||||||
|
app:enterAnim="@anim/nav_default_enter_anim"
|
||||||
|
app:exitAnim="@anim/nav_default_exit_anim"
|
||||||
|
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||||
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/genre_detail_fragment"
|
android:id="@+id/genre_detail_fragment"
|
||||||
|
@ -73,14 +86,14 @@
|
||||||
android:name="genreId"
|
android:name="genreId"
|
||||||
app:argType="long" />
|
app:argType="long" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_go_artist"
|
android:id="@+id/action_show_artist"
|
||||||
app:destination="@id/artist_detail_fragment"
|
app:destination="@id/artist_detail_fragment"
|
||||||
app:enterAnim="@anim/nav_default_enter_anim"
|
app:enterAnim="@anim/nav_default_enter_anim"
|
||||||
app:exitAnim="@anim/nav_default_exit_anim"
|
app:exitAnim="@anim/nav_default_exit_anim"
|
||||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_go_album"
|
android:id="@+id/action_show_album"
|
||||||
app:destination="@id/album_detail_fragment"
|
app:destination="@id/album_detail_fragment"
|
||||||
app:enterAnim="@anim/nav_default_enter_anim"
|
app:enterAnim="@anim/nav_default_enter_anim"
|
||||||
app:exitAnim="@anim/nav_default_exit_anim"
|
app:exitAnim="@anim/nav_default_exit_anim"
|
||||||
|
@ -92,11 +105,6 @@
|
||||||
android:name="org.oxycblt.auxio.songs.SongsFragment"
|
android:name="org.oxycblt.auxio.songs.SongsFragment"
|
||||||
android:label="fragment_songs"
|
android:label="fragment_songs"
|
||||||
tools:layout="@layout/fragment_songs" />
|
tools:layout="@layout/fragment_songs" />
|
||||||
<fragment
|
|
||||||
android:id="@+id/settings_fragment"
|
|
||||||
android:name="org.oxycblt.auxio.settings.SettingsFragment"
|
|
||||||
android:label="SettingsFragment"
|
|
||||||
tools:layout="@layout/fragment_settings" />
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/search_fragment"
|
android:id="@+id/search_fragment"
|
||||||
android:name="org.oxycblt.auxio.search.SearchFragment"
|
android:name="org.oxycblt.auxio.search.SearchFragment"
|
||||||
|
@ -124,4 +132,9 @@
|
||||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/settings_fragment"
|
||||||
|
android:name="org.oxycblt.auxio.settings.SettingsFragment"
|
||||||
|
android:label="SettingsFragment"
|
||||||
|
tools:layout="@layout/fragment_settings" />
|
||||||
</navigation>
|
</navigation>
|
Loading…
Reference in a new issue