home: re-add grid spans

Re-add grid spans to HomeFragment when on landscape mode.
This commit is contained in:
OxygenCobalt 2021-08-22 09:01:30 -06:00
parent a3e7cb93aa
commit b5c5fabad0
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
10 changed files with 72 additions and 166 deletions

View file

@ -26,17 +26,12 @@ 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.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Parent
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder
import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder
import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
/**
* An adapter for displaying library items. Supports [Parent]s only.
* @author OxygenCobalt
*/
class HomeAdapter( class HomeAdapter(
private val doOnClick: (data: BaseModel) -> Unit, private val doOnClick: (data: BaseModel) -> Unit,
private val doOnLongClick: (view: View, data: BaseModel) -> Unit private val doOnLongClick: (view: View, data: BaseModel) -> Unit

View file

@ -25,7 +25,9 @@ import android.view.ViewGroup
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.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.MainFragmentDirections
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
@ -35,12 +37,15 @@ import org.oxycblt.auxio.home.pager.ArtistListFragment
import org.oxycblt.auxio.home.pager.GenreListFragment import org.oxycblt.auxio.home.pager.GenreListFragment
import org.oxycblt.auxio.home.pager.SongListFragment import org.oxycblt.auxio.home.pager.SongListFragment
import org.oxycblt.auxio.logD import org.oxycblt.auxio.logD
import org.oxycblt.auxio.logE
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.PlaybackViewModel
import java.lang.Exception
/** /**
* The main "Launching Point" fragment of Auxio, allowing navigation to the detail * The main "Launching Point" fragment of Auxio, allowing navigation to the detail
* views for each respective fragment. * views for each respective fragment.
* TODO: Re-add sorting (but new and improved) * TODO: Re-add sorting (but new and improved)
* TODO: Fix issue where elevation will act wrong when switching tabs
* @author OxygenCobalt * @author OxygenCobalt
*/ */
class HomeFragment : Fragment() { class HomeFragment : Fragment() {

View file

@ -23,17 +23,16 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.databinding.FragmentHomeListBinding
import org.oxycblt.auxio.home.HomeAdapter import org.oxycblt.auxio.home.HomeAdapter
import org.oxycblt.auxio.home.HomeFragmentDirections import org.oxycblt.auxio.home.HomeFragmentDirections
import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.spans
import org.oxycblt.auxio.ui.newMenu import org.oxycblt.auxio.ui.newMenu
class AlbumListFragment : Fragment() { class AlbumListFragment : Fragment() {
private val playbackModel: PlaybackViewModel by viewModels()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -41,18 +40,25 @@ class AlbumListFragment : Fragment() {
): View { ): View {
val binding = FragmentHomeListBinding.inflate(inflater) val binding = FragmentHomeListBinding.inflate(inflater)
val adapter = HomeAdapter( val homeAdapter = HomeAdapter(
doOnClick = { item -> doOnClick = { item ->
HomeFragmentDirections.actionShowAlbum(item.id) findNavController().navigate(HomeFragmentDirections.actionShowAlbum(item.id))
}, },
::newMenu ::newMenu
) )
adapter.updateData(MusicStore.getInstance().albums) homeAdapter.updateData(MusicStore.getInstance().albums)
// --- UI SETUP --- // --- UI SETUP ---
binding.homeRecycler.adapter = adapter binding.homeRecycler.apply {
adapter = homeAdapter
setHasFixedSize(true)
if (spans != 1) {
layoutManager = GridLayoutManager(requireContext(), spans)
}
}
return binding.root return binding.root
} }

View file

@ -23,17 +23,16 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.databinding.FragmentHomeListBinding
import org.oxycblt.auxio.home.HomeAdapter import org.oxycblt.auxio.home.HomeAdapter
import org.oxycblt.auxio.home.HomeFragmentDirections import org.oxycblt.auxio.home.HomeFragmentDirections
import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.spans
import org.oxycblt.auxio.ui.newMenu import org.oxycblt.auxio.ui.newMenu
class ArtistListFragment : Fragment() { class ArtistListFragment : Fragment() {
private val playbackModel: PlaybackViewModel by viewModels()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -41,18 +40,25 @@ class ArtistListFragment : Fragment() {
): View { ): View {
val binding = FragmentHomeListBinding.inflate(inflater) val binding = FragmentHomeListBinding.inflate(inflater)
val adapter = HomeAdapter( val homeAdapter = HomeAdapter(
doOnClick = { item -> doOnClick = { item ->
HomeFragmentDirections.actionShowArtist(item.id) findNavController().navigate(HomeFragmentDirections.actionShowArtist(item.id))
}, },
::newMenu ::newMenu
) )
adapter.updateData(MusicStore.getInstance().artists) homeAdapter.updateData(MusicStore.getInstance().artists)
// --- UI SETUP --- // --- UI SETUP ---
binding.homeRecycler.adapter = adapter binding.homeRecycler.apply {
adapter = homeAdapter
setHasFixedSize(true)
if (spans != 1) {
layoutManager = GridLayoutManager(requireContext(), spans)
}
}
return binding.root return binding.root
} }

View file

@ -23,17 +23,16 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.databinding.FragmentHomeListBinding
import org.oxycblt.auxio.home.HomeAdapter import org.oxycblt.auxio.home.HomeAdapter
import org.oxycblt.auxio.home.HomeFragmentDirections import org.oxycblt.auxio.home.HomeFragmentDirections
import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.spans
import org.oxycblt.auxio.ui.newMenu import org.oxycblt.auxio.ui.newMenu
class GenreListFragment : Fragment() { class GenreListFragment : Fragment() {
private val playbackModel: PlaybackViewModel by viewModels()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -41,18 +40,25 @@ class GenreListFragment : Fragment() {
): View { ): View {
val binding = FragmentHomeListBinding.inflate(inflater) val binding = FragmentHomeListBinding.inflate(inflater)
val adapter = HomeAdapter( val homeAdapter = HomeAdapter(
doOnClick = { item -> doOnClick = { item ->
HomeFragmentDirections.actionShowGenre(item.id) findNavController().navigate(HomeFragmentDirections.actionShowGenre(item.id))
}, },
::newMenu ::newMenu
) )
adapter.updateData(MusicStore.getInstance().genres) homeAdapter.updateData(MusicStore.getInstance().genres)
// --- UI SETUP --- // --- UI SETUP ---
binding.homeRecycler.adapter = adapter binding.homeRecycler.apply {
adapter = homeAdapter
setHasFixedSize(true)
if (spans != 1) {
layoutManager = GridLayoutManager(requireContext(), spans)
}
}
return binding.root return binding.root
} }

View file

@ -24,11 +24,13 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.databinding.FragmentHomeListBinding
import org.oxycblt.auxio.home.HomeAdapter import org.oxycblt.auxio.home.HomeAdapter
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
import org.oxycblt.auxio.spans
import org.oxycblt.auxio.ui.newMenu import org.oxycblt.auxio.ui.newMenu
class SongListFragment : Fragment() { class SongListFragment : Fragment() {
@ -41,18 +43,25 @@ class SongListFragment : Fragment() {
): View { ): View {
val binding = FragmentHomeListBinding.inflate(inflater) val binding = FragmentHomeListBinding.inflate(inflater)
val adapter = HomeAdapter( val homeAdapter = HomeAdapter(
doOnClick = { item -> doOnClick = { item ->
playbackModel.playSong(item as Song) playbackModel.playSong(item as Song)
}, },
::newMenu ::newMenu
) )
adapter.updateData(MusicStore.getInstance().songs) homeAdapter.updateData(MusicStore.getInstance().songs)
// --- UI SETUP --- // --- UI SETUP ---
binding.homeRecycler.adapter = adapter binding.homeRecycler.apply {
adapter = homeAdapter
setHasFixedSize(true)
if (spans != 1) {
layoutManager = GridLayoutManager(requireContext(), spans)
}
}
return binding.root return binding.root
} }

View file

@ -1,133 +0,0 @@
/*
* Copyright (c) 2021 Auxio Project
* SlideLinearLayout.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.ui
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.logE
import java.lang.reflect.Field
/**
* Hack layout that fixes an issue where disappearing views would draw over non-disappearing
* views when animated with a stock LayoutTransition. If something breaks on the playback controls
* or nav bar, this is probably the culprit.
*
* "But oxygencobalt, couldn't you just write your own animation code and run that instea-"
* **NO.**
*
* Adapted from this StackOverflow answer:
* https://stackoverflow.com/a/35087229
* @author OxygenCobalt
*/
class SlideLinearLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = -1
) : LinearLayout(context, attrs, defStyleAttr) {
@SuppressLint("DiscouragedPrivateApi")
private val disappearingChildrenField: Field? = try {
// We need to read this field to correctly draw the disappearing children
// If google ever hides this API I am going to scream, because its their busted
// ViewGroup code that forces me to do this in the first place
ViewGroup::class.java.getDeclaredField("mDisappearingChildren").also {
it.isAccessible = true
}
} catch (e: NoSuchFieldException) {
logE("Could not get mDisappearingChildren. This is very ungood.")
null
}
private var disappearingChildren: List<View>? = null
private var dumpView: View? = null
private var doDrawingTrick: Boolean = false
init {
if (disappearingChildrenField != null) {
// Create a invisible junk view and add it, which makes all the magic happen [I think].
dumpView = View(context)
addView(dumpView, 0, 0)
}
}
override fun dispatchDraw(canvas: Canvas?) {
doDrawingTrick = beforeDispatchDraw()
super.dispatchDraw(canvas)
if (doDrawingTrick) {
doDrawingTrick = false
}
}
override fun drawChild(canvas: Canvas?, child: View?, drawingTime: Long): Boolean {
val children = getDisappearingChildren()
if (doDrawingTrick && children != null) {
// Use the dump view as a marker for when to do the trick
if (child == dumpView) {
// I dont even know what this does.
var consumed = false
children.forEach { view ->
consumed = consumed || super.drawChild(canvas, view, drawingTime)
}
return consumed
} else if (children.contains(child)) {
// Ignore the disappearing children
return false
}
}
return super.drawChild(canvas, child, drawingTime)
}
private fun beforeDispatchDraw(): Boolean {
val children = getDisappearingChildren()
// Dont do trick if there are no disappearing children or if there arent any children other
// than the dump view.
if (children == null || children.isEmpty() || childCount <= 1) {
return false
}
return true
}
private fun getDisappearingChildren(): List<View>? {
if (disappearingChildrenField == null || disappearingChildren != null) {
return disappearingChildren
}
try {
@Suppress("UNCHECKED_CAST")
disappearingChildren = disappearingChildrenField.get(this) as List<View>?
} catch (e: Exception) {
logD("Could not get list of disappearing children.")
}
return disappearingChildren
}
}

View file

@ -44,7 +44,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:listitem="@layout/item_artist" /> tools:layout="@layout/fragment_home_list" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout> </layout>

View file

@ -21,6 +21,15 @@
<item <item
android:id="@+id/option_sort_alpha_up" android:id="@+id/option_sort_alpha_up"
android:title="@string/lbl_sort_alpha_up" /> android:title="@string/lbl_sort_alpha_up" />
<item
android:id="@+id/option_sort_artist"
android:title="@string/lbl_sort_artist" />
<item
android:id="@+id/option_sort_album"
android:title="@string/lbl_sort_album" />
<item
android:id="@+id/option_sort_year"
android:title="@string/lbl_sort_year" />
</group> </group>
</menu> </menu>
</item> </item>

View file

@ -25,6 +25,9 @@
<string name="lbl_sort">Sort</string> <string name="lbl_sort">Sort</string>
<string name="lbl_sort_alpha_down">Ascending</string> <string name="lbl_sort_alpha_down">Ascending</string>
<string name="lbl_sort_alpha_up">Descending</string> <string name="lbl_sort_alpha_up">Descending</string>
<string name="lbl_sort_artist">Artist</string>
<string name="lbl_sort_album">Album</string>
<string name="lbl_sort_year">Year</string>
<string name="lbl_play">Play</string> <string name="lbl_play">Play</string>
<string name="lbl_shuffle">Shuffle</string> <string name="lbl_shuffle">Shuffle</string>