Standardize fragment creation
Standardize the code layout for fragment creation.
This commit is contained in:
parent
711d9a0b00
commit
7928347f9b
8 changed files with 133 additions and 118 deletions
|
@ -33,10 +33,6 @@ class MainFragment : Fragment() {
|
|||
): View? {
|
||||
val binding = FragmentMainBinding.inflate(inflater)
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
binding.mainViewPager.adapter = PagerAdapter()
|
||||
|
||||
val colorActive = accent.first.toColor(requireContext())
|
||||
val colorInactive = getTransparentAccent(
|
||||
requireContext(),
|
||||
|
@ -44,6 +40,11 @@ class MainFragment : Fragment() {
|
|||
getInactiveAlpha(accent.first)
|
||||
)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.mainViewPager.adapter = PagerAdapter()
|
||||
|
||||
// Link the ViewPager & Tab View
|
||||
TabLayoutMediator(binding.mainTabs, binding.mainViewPager) { tab, position ->
|
||||
tab.icon = ContextCompat.getDrawable(requireContext(), tabIcons[position])
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.oxycblt.auxio.detail
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
|
@ -16,7 +15,7 @@ import org.oxycblt.auxio.detail.adapters.DetailSongAdapter
|
|||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.toColor
|
||||
import org.oxycblt.auxio.theme.disable
|
||||
|
||||
class AlbumDetailFragment : Fragment() {
|
||||
|
||||
|
@ -50,6 +49,8 @@ class AlbumDetailFragment : Fragment() {
|
|||
}
|
||||
)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.detailModel = detailModel
|
||||
binding.album = detailModel.currentAlbum.value!!
|
||||
|
@ -64,6 +65,25 @@ class AlbumDetailFragment : Fragment() {
|
|||
findNavController().navigateUp()
|
||||
}
|
||||
|
||||
// Don't enable the sort button if there's only one song [or less]
|
||||
if (detailModel.currentAlbum.value!!.numSongs < 2) {
|
||||
binding.albumSortButton.disable(requireContext())
|
||||
}
|
||||
|
||||
// -- VIEWMODEL SETUP ---
|
||||
|
||||
detailModel.albumSortMode.observe(viewLifecycleOwner) { mode ->
|
||||
Log.d(this::class.simpleName, "Updating sort mode to $mode")
|
||||
|
||||
// Update the current sort icon
|
||||
binding.albumSortButton.setImageResource(mode.iconRes)
|
||||
|
||||
// Then update the sort mode of the album adapter.
|
||||
songAdapter.submitList(
|
||||
mode.getSortedSongList(detailModel.currentAlbum.value!!.songs)
|
||||
)
|
||||
}
|
||||
|
||||
// If the album was shown directly from LibraryFragment, Then enable the ability to
|
||||
// navigate upwards to the parent artist
|
||||
if (args.enableParentNav) {
|
||||
|
@ -84,27 +104,6 @@ class AlbumDetailFragment : Fragment() {
|
|||
binding.albumArtist.setBackgroundResource(R.drawable.ripple)
|
||||
}
|
||||
|
||||
detailModel.albumSortMode.observe(viewLifecycleOwner) { mode ->
|
||||
Log.d(this::class.simpleName, "Updating sort mode to $mode")
|
||||
|
||||
// Update the current sort icon
|
||||
binding.albumSortButton.setImageResource(mode.iconRes)
|
||||
|
||||
// Then update the sort mode of the album adapter.
|
||||
songAdapter.submitList(
|
||||
mode.getSortedSongList(detailModel.currentAlbum.value!!.songs)
|
||||
)
|
||||
}
|
||||
|
||||
// Don't enable the sort button if there's only one song [or less]
|
||||
if (detailModel.currentAlbum.value!!.numSongs < 2) {
|
||||
binding.albumSortButton.imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(requireContext())
|
||||
)
|
||||
|
||||
binding.albumSortButton.isEnabled = false
|
||||
}
|
||||
|
||||
Log.d(this::class.simpleName, "Fragment created.")
|
||||
|
||||
return binding.root
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.oxycblt.auxio.detail
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
|
@ -10,13 +9,12 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding
|
||||
import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.toColor
|
||||
import org.oxycblt.auxio.theme.disable
|
||||
|
||||
class ArtistDetailFragment : Fragment() {
|
||||
|
||||
|
@ -56,19 +54,28 @@ class ArtistDetailFragment : Fragment() {
|
|||
}
|
||||
)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.detailModel = detailModel
|
||||
binding.artist = detailModel.currentArtist.value!!
|
||||
|
||||
binding.artistToolbar.setNavigationOnClickListener {
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
|
||||
// Disable the sort button if there is only one album [Or less]
|
||||
if (detailModel.currentArtist.value!!.numAlbums < 2) {
|
||||
binding.artistSortButton.disable(requireContext())
|
||||
}
|
||||
|
||||
binding.artistAlbumRecycler.apply {
|
||||
adapter = albumAdapter
|
||||
applyDivider()
|
||||
setHasFixedSize(true)
|
||||
}
|
||||
|
||||
binding.artistToolbar.setNavigationOnClickListener {
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
detailModel.artistSortMode.observe(viewLifecycleOwner) { mode ->
|
||||
Log.d(this::class.simpleName, "Updating sort mode to $mode")
|
||||
|
@ -82,15 +89,6 @@ class ArtistDetailFragment : Fragment() {
|
|||
)
|
||||
}
|
||||
|
||||
// Don't enable the sort button if there is only one album [Or less]
|
||||
if (detailModel.currentArtist.value!!.numAlbums < 2) {
|
||||
binding.artistSortButton.imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(requireContext())
|
||||
)
|
||||
|
||||
binding.artistSortButton.isEnabled = false
|
||||
}
|
||||
|
||||
Log.d(this::class.simpleName, "Fragment created.")
|
||||
|
||||
return binding.root
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.oxycblt.auxio.detail
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
|
@ -10,13 +9,12 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentGenreDetailBinding
|
||||
import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.toColor
|
||||
import org.oxycblt.auxio.theme.disable
|
||||
|
||||
class GenreDetailFragment : Fragment() {
|
||||
|
||||
|
@ -56,18 +54,29 @@ class GenreDetailFragment : Fragment() {
|
|||
}
|
||||
)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.detailModel = detailModel
|
||||
binding.genre = detailModel.currentGenre.value
|
||||
|
||||
binding.genreArtistRecycler.adapter = artistAdapter
|
||||
binding.genreArtistRecycler.applyDivider()
|
||||
binding.genreArtistRecycler.setHasFixedSize(true)
|
||||
|
||||
binding.genreToolbar.setNavigationOnClickListener {
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
|
||||
// Disable the sort button if there is only one artist [Or less]
|
||||
if (detailModel.currentGenre.value!!.numArtists < 2) {
|
||||
binding.genreSortButton.disable(requireContext())
|
||||
}
|
||||
|
||||
binding.genreArtistRecycler.apply {
|
||||
adapter = artistAdapter
|
||||
applyDivider()
|
||||
setHasFixedSize(true)
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
detailModel.genreSortMode.observe(viewLifecycleOwner) { mode ->
|
||||
Log.d(this::class.simpleName, "Updating sort mode to $mode")
|
||||
|
||||
|
@ -80,15 +89,6 @@ class GenreDetailFragment : Fragment() {
|
|||
)
|
||||
}
|
||||
|
||||
// Don't enable the sort button if there is only one artist [Or less]
|
||||
if (detailModel.currentGenre.value!!.numArtists < 2) {
|
||||
binding.genreSortButton.imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(requireContext())
|
||||
)
|
||||
|
||||
binding.genreSortButton.isEnabled = false
|
||||
}
|
||||
|
||||
Log.d(this::class.simpleName, "Fragment created.")
|
||||
|
||||
return binding.root
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.view.LayoutInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.forEach
|
||||
|
@ -50,70 +49,74 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
navToItem(it)
|
||||
}
|
||||
|
||||
// Toolbar setup
|
||||
binding.libraryToolbar.overflowIcon = ContextCompat.getDrawable(
|
||||
requireContext(), R.drawable.ic_sort_none
|
||||
)
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.libraryToolbar.menu.apply {
|
||||
val item = findItem(R.id.action_search)
|
||||
val searchView = item.actionView as SearchView
|
||||
binding.libraryToolbar.apply {
|
||||
overflowIcon = ContextCompat.getDrawable(
|
||||
requireContext(), R.drawable.ic_sort_none
|
||||
)
|
||||
|
||||
searchView.findViewById<ImageView>(androidx.appcompat.R.id.search_go_btn)
|
||||
.setImageResource(R.drawable.ic_back)
|
||||
setOnMenuItemClickListener {
|
||||
if (it.itemId != R.id.action_search) {
|
||||
libraryModel.updateSortMode(it)
|
||||
} else {
|
||||
// Do whatever this is in order to make the SearchView focusable.
|
||||
(it.actionView as SearchView).isIconified = false
|
||||
|
||||
searchView.setOnQueryTextListener(this@LibraryFragment)
|
||||
searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
|
||||
libraryModel.updateSearchFocusStatus(hasFocus)
|
||||
item.isVisible = !hasFocus
|
||||
// Then also do a basic animation
|
||||
TransitionManager.beginDelayedTransition(
|
||||
binding.libraryToolbar, Fade()
|
||||
)
|
||||
it.expandActionView()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
|
||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
||||
// When opened, update the adapter to the SearchAdapter, and make the sorting
|
||||
// group invisible. The query is also reset, as if the Auxio process is
|
||||
// killed in the background while still on the search adapter, then the
|
||||
// search query will stick around if its opened again
|
||||
// TODO: Couldn't you just try to restore the search state on restart?
|
||||
binding.libraryRecycler.adapter = searchAdapter
|
||||
setGroupVisible(R.id.group_sorting, false)
|
||||
libraryModel.resetQuery()
|
||||
menu.apply {
|
||||
val item = findItem(R.id.action_search)
|
||||
val searchView = item.actionView as SearchView
|
||||
|
||||
return true
|
||||
searchView.setOnQueryTextListener(this@LibraryFragment)
|
||||
searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
|
||||
libraryModel.updateSearchFocusStatus(hasFocus)
|
||||
item.isVisible = !hasFocus
|
||||
}
|
||||
|
||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
||||
// When closed, make the sorting icon visible again, change back to
|
||||
// LibraryAdapter, and reset the query.
|
||||
binding.libraryRecycler.adapter = libraryAdapter
|
||||
setGroupVisible(R.id.group_sorting, true)
|
||||
libraryModel.resetQuery()
|
||||
item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
|
||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
||||
// When opened, update the adapter to the SearchAdapter, and make the
|
||||
// sorting group invisible. The query is also reset, as if the Auxio process
|
||||
// is killed in the background while still on the search adapter, then the
|
||||
// search query will stick around if its opened again
|
||||
// TODO: Couldn't you just try to restore the search state on restart?
|
||||
binding.libraryRecycler.adapter = searchAdapter
|
||||
setGroupVisible(R.id.group_sorting, false)
|
||||
libraryModel.resetQuery()
|
||||
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
binding.libraryToolbar.setOnMenuItemClickListener {
|
||||
if (it.itemId != R.id.action_search) {
|
||||
libraryModel.updateSortMode(it)
|
||||
} else {
|
||||
// Do whatever this is in order to make the SearchView focusable.
|
||||
(it.actionView as SearchView).isIconified = false
|
||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
||||
// When closed, make the sorting icon visible again, change back to
|
||||
// LibraryAdapter, and reset the query.
|
||||
binding.libraryRecycler.adapter = libraryAdapter
|
||||
setGroupVisible(R.id.group_sorting, true)
|
||||
libraryModel.resetQuery()
|
||||
|
||||
// Then also do a basic animation
|
||||
TransitionManager.beginDelayedTransition(
|
||||
binding.libraryToolbar, Fade()
|
||||
)
|
||||
it.expandActionView()
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// RecyclerView setup
|
||||
binding.libraryRecycler.adapter = libraryAdapter
|
||||
binding.libraryRecycler.applyDivider()
|
||||
binding.libraryRecycler.setHasFixedSize(true)
|
||||
binding.libraryRecycler.apply {
|
||||
adapter = libraryAdapter
|
||||
|
||||
applyDivider()
|
||||
setHasFixedSize(true)
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
libraryModel.sortMode.observe(viewLifecycleOwner) { mode ->
|
||||
Log.d(this::class.simpleName, "Updating sort mode to $mode")
|
||||
|
|
|
@ -25,14 +25,18 @@ class SongsFragment : Fragment() {
|
|||
): View? {
|
||||
val binding = FragmentSongsBinding.inflate(inflater)
|
||||
|
||||
binding.songRecycler.adapter = SongAdapter(
|
||||
musicModel.songs.value!!,
|
||||
ClickListener { song ->
|
||||
Log.d(this::class.simpleName, song.name)
|
||||
}
|
||||
)
|
||||
binding.songRecycler.applyDivider()
|
||||
binding.songRecycler.setHasFixedSize(true)
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.songRecycler.apply {
|
||||
adapter = SongAdapter(
|
||||
musicModel.songs.value!!,
|
||||
ClickListener { song ->
|
||||
Log.d(this::class.simpleName, song.name)
|
||||
}
|
||||
)
|
||||
applyDivider()
|
||||
setHasFixedSize(true)
|
||||
}
|
||||
|
||||
Log.d(this::class.simpleName, "Fragment created.")
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package org.oxycblt.auxio.theme
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.util.TypedValue
|
||||
import android.view.MenuItem
|
||||
import android.widget.ImageButton
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
|
@ -91,6 +93,14 @@ fun MenuItem.applyColor(color: Int) {
|
|||
}
|
||||
}
|
||||
|
||||
fun ImageButton.disable(context: Context) {
|
||||
imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(context)
|
||||
)
|
||||
|
||||
isEnabled = false
|
||||
}
|
||||
|
||||
// Apply a custom vertical divider
|
||||
fun RecyclerView.applyDivider() {
|
||||
val div = DividerItemDecoration(
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<item name="android:textColor">?android:attr/colorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="Toolbar.SearchViewStyle" parent="Widget.AppCompat.SearchView"/>
|
||||
<style name="Toolbar.SearchViewStyle" parent="Widget.AppCompat.SearchView" />
|
||||
|
||||
<style name="DetailHeader">
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
|
||||
|
|
Loading…
Reference in a new issue