home: re-add grid spans
Re-add grid spans to HomeFragment when on landscape mode.
This commit is contained in:
parent
a3e7cb93aa
commit
b5c5fabad0
10 changed files with 72 additions and 166 deletions
|
@ -26,17 +26,12 @@ import org.oxycblt.auxio.music.Album
|
|||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Parent
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
|
||||
|
||||
/**
|
||||
* An adapter for displaying library items. Supports [Parent]s only.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class HomeAdapter(
|
||||
private val doOnClick: (data: BaseModel) -> Unit,
|
||||
private val doOnLongClick: (view: View, data: BaseModel) -> Unit
|
||||
|
|
|
@ -25,7 +25,9 @@ import android.view.ViewGroup
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import org.oxycblt.auxio.MainFragmentDirections
|
||||
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.SongListFragment
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.logE
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import java.lang.Exception
|
||||
|
||||
/**
|
||||
* The main "Launching Point" fragment of Auxio, allowing navigation to the detail
|
||||
* views for each respective fragment.
|
||||
* TODO: Re-add sorting (but new and improved)
|
||||
* TODO: Fix issue where elevation will act wrong when switching tabs
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class HomeFragment : Fragment() {
|
||||
|
|
|
@ -23,17 +23,16 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.home.HomeAdapter
|
||||
import org.oxycblt.auxio.home.HomeFragmentDirections
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.spans
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
|
||||
class AlbumListFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
@ -41,18 +40,25 @@ class AlbumListFragment : Fragment() {
|
|||
): View {
|
||||
val binding = FragmentHomeListBinding.inflate(inflater)
|
||||
|
||||
val adapter = HomeAdapter(
|
||||
val homeAdapter = HomeAdapter(
|
||||
doOnClick = { item ->
|
||||
HomeFragmentDirections.actionShowAlbum(item.id)
|
||||
findNavController().navigate(HomeFragmentDirections.actionShowAlbum(item.id))
|
||||
},
|
||||
::newMenu
|
||||
)
|
||||
|
||||
adapter.updateData(MusicStore.getInstance().albums)
|
||||
homeAdapter.updateData(MusicStore.getInstance().albums)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.homeRecycler.adapter = adapter
|
||||
binding.homeRecycler.apply {
|
||||
adapter = homeAdapter
|
||||
setHasFixedSize(true)
|
||||
|
||||
if (spans != 1) {
|
||||
layoutManager = GridLayoutManager(requireContext(), spans)
|
||||
}
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
|
|
@ -23,17 +23,16 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.home.HomeAdapter
|
||||
import org.oxycblt.auxio.home.HomeFragmentDirections
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.spans
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
|
||||
class ArtistListFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
@ -41,18 +40,25 @@ class ArtistListFragment : Fragment() {
|
|||
): View {
|
||||
val binding = FragmentHomeListBinding.inflate(inflater)
|
||||
|
||||
val adapter = HomeAdapter(
|
||||
val homeAdapter = HomeAdapter(
|
||||
doOnClick = { item ->
|
||||
HomeFragmentDirections.actionShowArtist(item.id)
|
||||
findNavController().navigate(HomeFragmentDirections.actionShowArtist(item.id))
|
||||
},
|
||||
::newMenu
|
||||
)
|
||||
|
||||
adapter.updateData(MusicStore.getInstance().artists)
|
||||
homeAdapter.updateData(MusicStore.getInstance().artists)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.homeRecycler.adapter = adapter
|
||||
binding.homeRecycler.apply {
|
||||
adapter = homeAdapter
|
||||
setHasFixedSize(true)
|
||||
|
||||
if (spans != 1) {
|
||||
layoutManager = GridLayoutManager(requireContext(), spans)
|
||||
}
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
|
|
@ -23,17 +23,16 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.home.HomeAdapter
|
||||
import org.oxycblt.auxio.home.HomeFragmentDirections
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.spans
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
|
||||
class GenreListFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
@ -41,18 +40,25 @@ class GenreListFragment : Fragment() {
|
|||
): View {
|
||||
val binding = FragmentHomeListBinding.inflate(inflater)
|
||||
|
||||
val adapter = HomeAdapter(
|
||||
val homeAdapter = HomeAdapter(
|
||||
doOnClick = { item ->
|
||||
HomeFragmentDirections.actionShowGenre(item.id)
|
||||
findNavController().navigate(HomeFragmentDirections.actionShowGenre(item.id))
|
||||
},
|
||||
::newMenu
|
||||
)
|
||||
|
||||
adapter.updateData(MusicStore.getInstance().genres)
|
||||
homeAdapter.updateData(MusicStore.getInstance().genres)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.homeRecycler.adapter = adapter
|
||||
binding.homeRecycler.apply {
|
||||
adapter = homeAdapter
|
||||
setHasFixedSize(true)
|
||||
|
||||
if (spans != 1) {
|
||||
layoutManager = GridLayoutManager(requireContext(), spans)
|
||||
}
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
|
|
@ -24,11 +24,13 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import org.oxycblt.auxio.databinding.FragmentHomeListBinding
|
||||
import org.oxycblt.auxio.home.HomeAdapter
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.spans
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
|
||||
class SongListFragment : Fragment() {
|
||||
|
@ -41,18 +43,25 @@ class SongListFragment : Fragment() {
|
|||
): View {
|
||||
val binding = FragmentHomeListBinding.inflate(inflater)
|
||||
|
||||
val adapter = HomeAdapter(
|
||||
val homeAdapter = HomeAdapter(
|
||||
doOnClick = { item ->
|
||||
playbackModel.playSong(item as Song)
|
||||
},
|
||||
::newMenu
|
||||
)
|
||||
|
||||
adapter.updateData(MusicStore.getInstance().songs)
|
||||
homeAdapter.updateData(MusicStore.getInstance().songs)
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
||||
binding.homeRecycler.adapter = adapter
|
||||
binding.homeRecycler.apply {
|
||||
adapter = homeAdapter
|
||||
setHasFixedSize(true)
|
||||
|
||||
if (spans != 1) {
|
||||
layoutManager = GridLayoutManager(requireContext(), spans)
|
||||
}
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
android:layout_height="match_parent"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
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>
|
||||
</layout>
|
|
@ -21,6 +21,15 @@
|
|||
<item
|
||||
android:id="@+id/option_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>
|
||||
</menu>
|
||||
</item>
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
<string name="lbl_sort">Sort</string>
|
||||
<string name="lbl_sort_alpha_down">Ascending</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_shuffle">Shuffle</string>
|
||||
|
|
Loading…
Reference in a new issue