android: Use autofit grid for games fragment

This commit is contained in:
Charles Lombardo 2023-03-23 13:26:05 -04:00 committed by bunnei
parent 9cb7e7072d
commit 3878c6ced1
3 changed files with 72 additions and 28 deletions

View File

@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.layout
import android.content.Context
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.Recycler
import org.yuzu.yuzu_emu.R
/**
* Cut down version of the solution provided here
* https://stackoverflow.com/questions/26666143/recyclerview-gridlayoutmanager-how-to-auto-detect-span-count
*/
class AutofitGridLayoutManager(
context: Context,
columnWidth: Int
) : GridLayoutManager(context, 1) {
private var columnWidth = 0
private var isColumnWidthChanged = true
private var lastWidth = 0
private var lastHeight = 0
init {
setColumnWidth(checkedColumnWidth(context, columnWidth))
}
private fun checkedColumnWidth(context: Context, columnWidth: Int): Int {
var newColumnWidth = columnWidth
if (newColumnWidth <= 0) {
newColumnWidth = context.resources.getDimensionPixelSize(R.dimen.spacing_xtralarge)
}
return newColumnWidth
}
private fun setColumnWidth(newColumnWidth: Int) {
if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
columnWidth = newColumnWidth
isColumnWidthChanged = true
}
}
override fun onLayoutChildren(recycler: Recycler, state: RecyclerView.State) {
val width = width
val height = height
if (columnWidth > 0 && width > 0 && height > 0 && (isColumnWidthChanged || lastWidth != width || lastHeight != height)) {
val totalSpace: Int = if (orientation == VERTICAL) {
width - paddingRight - paddingLeft
} else {
height - paddingTop - paddingBottom
}
val spanCount = 1.coerceAtLeast(totalSpace / columnWidth)
setSpanCount(spanCount)
isColumnWidthChanged = false
}
lastWidth = width
lastHeight = height
super.onLayoutChildren(recycler, state)
}
}

View File

@ -8,22 +8,20 @@ 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 android.view.ViewTreeObserver.OnGlobalLayoutListener
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.adapters.GameAdapter import org.yuzu.yuzu_emu.adapters.GameAdapter
import org.yuzu.yuzu_emu.databinding.FragmentGridBinding import org.yuzu.yuzu_emu.databinding.FragmentGridBinding
import org.yuzu.yuzu_emu.layout.AutofitGridLayoutManager
class PlatformGamesFragment : Fragment(), PlatformGamesView { class PlatformGamesFragment : Fragment(), PlatformGamesView {
private val presenter = PlatformGamesPresenter(this) private val presenter = PlatformGamesPresenter(this)
private var adapter: GameAdapter? = null
private var _binding: FragmentGridBinding? = null private var _binding: FragmentGridBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
@ -39,27 +37,12 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
adapter = GameAdapter(requireActivity() as AppCompatActivity) binding.gridGames.apply {
layoutManager = AutofitGridLayoutManager(
// Organize our grid layout based on the current view. requireContext(),
if (isAdded) {
view.viewTreeObserver
.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (view.measuredWidth == 0) {
return
}
var columns = view.measuredWidth /
requireContext().resources.getDimensionPixelSize(R.dimen.card_width) requireContext().resources.getDimensionPixelSize(R.dimen.card_width)
if (columns == 0) { )
columns = 1 adapter = GameAdapter(requireActivity() as AppCompatActivity)
}
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
val layoutManager = GridLayoutManager(activity, columns)
binding.gridGames.layoutManager = layoutManager
binding.gridGames.adapter = adapter
}
})
} }
// Add swipe down to refresh gesture // Add swipe down to refresh gesture
@ -92,8 +75,8 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {
} }
override fun showGames(games: Cursor) { override fun showGames(games: Cursor) {
if (adapter != null) { if (binding.gridGames.adapter != null) {
adapter!!.swapCursor(games) (binding.gridGames.adapter as GameAdapter).swapCursor(games)
} }
updateTextView() updateTextView()
} }
@ -103,7 +86,7 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {
return return
binding.gamelistEmptyText.visibility = binding.gamelistEmptyText.visibility =
if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE if ((binding.gridGames.adapter as GameAdapter).itemCount == 0) View.VISIBLE else View.GONE
} }
private fun setInsets() { private fun setInsets() {

View File

@ -6,7 +6,7 @@
<dimen name="spacing_list">64dp</dimen> <dimen name="spacing_list">64dp</dimen>
<dimen name="spacing_fab">72dp</dimen> <dimen name="spacing_fab">72dp</dimen>
<dimen name="menu_width">256dp</dimen> <dimen name="menu_width">256dp</dimen>
<dimen name="card_width">150dp</dimen> <dimen name="card_width">170dp</dimen>
<dimen name="dialog_margin">20dp</dimen> <dimen name="dialog_margin">20dp</dimen>
<dimen name="elevated_app_bar">3dp</dimen> <dimen name="elevated_app_bar">3dp</dimen>