Merge pull request #11594 from t895/autofit-grid
Android: Responsive autofit grid
This commit is contained in:
commit
19e8569634
|
@ -0,0 +1,60 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.dolphinemu.dolphinemu.layout
|
||||
|
||||
import android.content.Context
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.Recycler
|
||||
import org.dolphinemu.dolphinemu.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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import android.os.Bundle;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -14,7 +13,7 @@ import androidx.core.graphics.Insets;
|
|||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
|
@ -22,13 +21,13 @@ import com.google.android.material.color.MaterialColors;
|
|||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.adapters.GameAdapter;
|
||||
import org.dolphinemu.dolphinemu.databinding.FragmentGridBinding;
|
||||
import org.dolphinemu.dolphinemu.layout.AutofitGridLayoutManager;
|
||||
import org.dolphinemu.dolphinemu.services.GameFileCacheManager;
|
||||
|
||||
public final class PlatformGamesFragment extends Fragment implements PlatformGamesView
|
||||
{
|
||||
private static final String ARG_PLATFORM = "platform";
|
||||
|
||||
private GameAdapter mAdapter;
|
||||
private SwipeRefreshLayout mSwipeRefresh;
|
||||
private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener;
|
||||
|
||||
|
@ -64,37 +63,12 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam
|
|||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState)
|
||||
{
|
||||
mSwipeRefresh = mBinding.swipeRefresh;
|
||||
mAdapter = new GameAdapter(requireActivity());
|
||||
|
||||
// Here we have to make sure the fragment is attached to an activity, wait for the layout
|
||||
// to be drawn, and make sure it is drawn with a width > 0 before finding the correct
|
||||
// span for our grid layout. Once drawn correctly, we can stop listening for layout changes.
|
||||
if (isAdded())
|
||||
{
|
||||
view.getViewTreeObserver()
|
||||
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
|
||||
{
|
||||
@Override
|
||||
public void onGlobalLayout()
|
||||
{
|
||||
if (mBinding.getRoot().getMeasuredWidth() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int columns = mBinding.getRoot().getMeasuredWidth() /
|
||||
requireContext().getResources().getDimensionPixelSize(R.dimen.card_width);
|
||||
if (columns == 0)
|
||||
{
|
||||
columns = 1;
|
||||
}
|
||||
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), columns);
|
||||
mBinding.gridGames.setLayoutManager(layoutManager);
|
||||
mBinding.gridGames.setAdapter(mAdapter);
|
||||
}
|
||||
});
|
||||
}
|
||||
GameAdapter adapter = new GameAdapter(requireActivity());
|
||||
adapter.setStateRestorationPolicy(
|
||||
RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
|
||||
mBinding.gridGames.setAdapter(adapter);
|
||||
mBinding.gridGames.setLayoutManager(new AutofitGridLayoutManager(requireContext(),
|
||||
getResources().getDimensionPixelSize(R.dimen.card_width)));
|
||||
|
||||
// Set theme color to the refresh animation's background
|
||||
mSwipeRefresh.setProgressBackgroundColorSchemeColor(
|
||||
|
@ -118,12 +92,6 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam
|
|||
mBinding = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshScreenshotAtPosition(int position)
|
||||
{
|
||||
mAdapter.notifyItemChanged(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(String gameId)
|
||||
{
|
||||
|
@ -133,17 +101,21 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam
|
|||
@Override
|
||||
public void showGames()
|
||||
{
|
||||
if (mAdapter != null)
|
||||
if (mBinding == null)
|
||||
return;
|
||||
|
||||
if (mBinding.gridGames.getAdapter() != null)
|
||||
{
|
||||
Platform platform = (Platform) getArguments().getSerializable(ARG_PLATFORM);
|
||||
mAdapter.swapDataSet(GameFileCacheManager.getGameFilesForPlatform(platform));
|
||||
((GameAdapter) mBinding.gridGames.getAdapter()).swapDataSet(
|
||||
GameFileCacheManager.getGameFilesForPlatform(platform));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refetchMetadata()
|
||||
{
|
||||
mAdapter.refetchMetadata();
|
||||
((GameAdapter) mBinding.gridGames.getAdapter()).refetchMetadata();
|
||||
}
|
||||
|
||||
public void setOnRefreshListener(@Nullable SwipeRefreshLayout.OnRefreshListener listener)
|
||||
|
|
|
@ -7,14 +7,6 @@ package org.dolphinemu.dolphinemu.ui.platform;
|
|||
*/
|
||||
public interface PlatformGamesView
|
||||
{
|
||||
/**
|
||||
* Tell the view that a certain game's screenshot has been updated,
|
||||
* and should be redrawn on-screen.
|
||||
*
|
||||
* @param position The index of the game that should be redrawn.
|
||||
*/
|
||||
void refreshScreenshotAtPosition(int position);
|
||||
|
||||
/**
|
||||
* Pass a click event to the view's Presenter. Typically called from the
|
||||
* view's list adapter.
|
||||
|
|
Loading…
Reference in New Issue