From 3878c6ced1e25265e1a84f85f23cebbd62ce98b8 Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Thu, 23 Mar 2023 13:26:05 -0400 Subject: [PATCH] android: Use autofit grid for games fragment --- .../layout/AutofitGridLayoutManager.kt | 61 +++++++++++++++++++ .../ui/platform/PlatformGamesFragment.kt | 37 +++-------- .../app/src/main/res/values/dimens.xml | 2 +- 3 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/layout/AutofitGridLayoutManager.kt diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/layout/AutofitGridLayoutManager.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/layout/AutofitGridLayoutManager.kt new file mode 100644 index 000000000..be5e4c86c --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/layout/AutofitGridLayoutManager.kt @@ -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) + } +} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt index 7b8d7c5a3..998a00847 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt @@ -8,22 +8,20 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.ViewTreeObserver.OnGlobalLayoutListener import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.updatePadding import androidx.fragment.app.Fragment -import androidx.recyclerview.widget.GridLayoutManager import com.google.android.material.color.MaterialColors import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.adapters.GameAdapter import org.yuzu.yuzu_emu.databinding.FragmentGridBinding +import org.yuzu.yuzu_emu.layout.AutofitGridLayoutManager class PlatformGamesFragment : Fragment(), PlatformGamesView { private val presenter = PlatformGamesPresenter(this) - private var adapter: GameAdapter? = null private var _binding: FragmentGridBinding? = null private val binding get() = _binding!! @@ -39,27 +37,12 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView { } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - adapter = GameAdapter(requireActivity() as AppCompatActivity) - - // Organize our grid layout based on the current view. - 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) - if (columns == 0) { - columns = 1 - } - view.viewTreeObserver.removeOnGlobalLayoutListener(this) - val layoutManager = GridLayoutManager(activity, columns) - binding.gridGames.layoutManager = layoutManager - binding.gridGames.adapter = adapter - } - }) + binding.gridGames.apply { + layoutManager = AutofitGridLayoutManager( + requireContext(), + requireContext().resources.getDimensionPixelSize(R.dimen.card_width) + ) + adapter = GameAdapter(requireActivity() as AppCompatActivity) } // Add swipe down to refresh gesture @@ -92,8 +75,8 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView { } override fun showGames(games: Cursor) { - if (adapter != null) { - adapter!!.swapCursor(games) + if (binding.gridGames.adapter != null) { + (binding.gridGames.adapter as GameAdapter).swapCursor(games) } updateTextView() } @@ -103,7 +86,7 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView { return 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() { diff --git a/src/android/app/src/main/res/values/dimens.xml b/src/android/app/src/main/res/values/dimens.xml index 0b028a167..5573d6922 100644 --- a/src/android/app/src/main/res/values/dimens.xml +++ b/src/android/app/src/main/res/values/dimens.xml @@ -6,7 +6,7 @@ 64dp 72dp 256dp - 150dp + 170dp 20dp 3dp