From c2cd43a822f04888cf2da44f1bb6a19bb683a3e1 Mon Sep 17 00:00:00 2001 From: Henrik Tunedal Date: Wed, 12 Jul 2023 01:20:57 +0200 Subject: [PATCH] Extract LatestLayoutPolicy class from LatestAdapter The policy class decides which item view types to show. See issue #2650. --- .../fdroid/views/main/LatestAdapter.java | 95 +++---------------- .../fdroid/views/main/LatestLayoutPolicy.java | 95 +++++++++++++++++++ .../fdroid/views/main/LatestViewBinder.java | 2 +- 3 files changed, 110 insertions(+), 82 deletions(-) create mode 100644 app/src/main/java/org/fdroid/fdroid/views/main/LatestLayoutPolicy.java diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/LatestAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/main/LatestAdapter.java index 740eb56a3..cdd889ee2 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/LatestAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/LatestAdapter.java @@ -1,20 +1,12 @@ package org.fdroid.fdroid.views.main; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Rect; -import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import org.fdroid.database.AppOverviewItem; -import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.R; import org.fdroid.fdroid.views.categories.AppCardController; @@ -24,11 +16,15 @@ public class LatestAdapter extends RecyclerView.Adapter { private List apps; private final AppCompatActivity activity; + private final LatestLayoutPolicy layoutPolicy; private final RecyclerView.ItemDecoration appListDecorator; + private final GridLayoutManager.SpanSizeLookup spanSizeLookup; LatestAdapter(AppCompatActivity activity) { this.activity = activity; - appListDecorator = new LatestAdapter.ItemDecorator(activity); + layoutPolicy = new LatestLayoutPolicy(activity); + appListDecorator = layoutPolicy.getItemDecoration(); + spanSizeLookup = new SpanSizeLookup(layoutPolicy); } @Override @@ -66,33 +62,7 @@ public class LatestAdapter extends RecyclerView.Adapter { @Override public int getItemViewType(int position) { - int relativePositionInCycle = position % 5; - - if (BuildConfig.FLAVOR.startsWith("basic")) { - if (relativePositionInCycle > 0) { - return R.id.latest_small_tile; - } else { - return R.id.latest_regular_list; - } - } - - if (position == 0) { - return R.id.latest_regular_list; - } else { - switch (relativePositionInCycle) { - case 1: - case 2: - return R.id.latest_large_tile; - - case 3: - case 4: - return R.id.latest_small_tile; - - case 0: - default: - return R.id.latest_regular_list; - } - } + return layoutPolicy.getItemViewType(position); } @Override @@ -115,57 +85,20 @@ public class LatestAdapter extends RecyclerView.Adapter { notifyDataSetChanged(); } - public static class SpanSizeLookup extends GridLayoutManager.SpanSizeLookup { - @Override - public int getSpanSize(int position) { - int relativePositionInCycle = position % 5; - if (relativePositionInCycle == 0) { - return 2; - } else { - return 1; - } - } + public GridLayoutManager.SpanSizeLookup getSpanSizeLookup() { + return spanSizeLookup; } - /** - * Applies padding to items, ensuring that the spacing on the left, centre, and right all match. - * The vertical padding is slightly shorter than the horizontal padding also. - * - * @see org.fdroid.fdroid.R.dimen#latest__padding__app_card__horizontal - * @see org.fdroid.fdroid.R.dimen#latest__padding__app_card__vertical - */ - private static class ItemDecorator extends RecyclerView.ItemDecoration { - private final Context context; + private static final class SpanSizeLookup extends GridLayoutManager.SpanSizeLookup { + private final LatestLayoutPolicy layoutPolicy; - ItemDecorator(Context context) { - this.context = context.getApplicationContext(); + private SpanSizeLookup(LatestLayoutPolicy layoutPolicy) { + this.layoutPolicy = layoutPolicy; } @Override - public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, RecyclerView parent, - @NonNull RecyclerView.State state) { - int position = parent.getChildAdapterPosition(view); - Resources resources = context.getResources(); - int horizontalPadding = (int) resources.getDimension(R.dimen.latest__padding__app_card__horizontal); - int verticalPadding = (int) resources.getDimension(R.dimen.latest__padding__app_card__vertical); - - int relativePositionInCycle = position % 5; - if (position == 0) { - outRect.set(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); - } else if (relativePositionInCycle != 0) { - // The item on the left will have both left and right padding. The item on the right - // will only have padding on the right. This will allow the same amount of padding - // on the left, centre, and right of the grid, rather than double the padding in the - // middle (which would happen if both left and right padding was set for both items). - boolean isLtr = ViewCompat.getLayoutDirection(parent) == ViewCompat.LAYOUT_DIRECTION_LTR; - boolean isAtStart = relativePositionInCycle == 1 || relativePositionInCycle == 3; - int paddingStart = isAtStart ? horizontalPadding : 0; - int paddingLeft = isLtr ? paddingStart : horizontalPadding; - int paddingRight = isLtr ? horizontalPadding : paddingStart; - outRect.set(paddingLeft, 0, paddingRight, verticalPadding); - } else { - outRect.set(horizontalPadding, 0, horizontalPadding, verticalPadding); - } + public int getSpanSize(int position) { + return layoutPolicy.getSpanSize(position); } } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/LatestLayoutPolicy.java b/app/src/main/java/org/fdroid/fdroid/views/main/LatestLayoutPolicy.java new file mode 100644 index 000000000..c4d79bd44 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/main/LatestLayoutPolicy.java @@ -0,0 +1,95 @@ +package org.fdroid.fdroid.views.main; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Rect; +import android.view.View; +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView; +import org.fdroid.fdroid.R; + +public class LatestLayoutPolicy { + private final Context context; + + public LatestLayoutPolicy(Context context) { + this.context = context.getApplicationContext(); + } + + public RecyclerView.ItemDecoration getItemDecoration() { + return new ItemDecorator(context); + } + + public int getItemViewType(int position) { + int relativePositionInCycle = position % 5; + + if (position == 0) { + return R.id.latest_regular_list; + } else { + switch (relativePositionInCycle) { + case 1: + case 2: + return R.id.latest_large_tile; + + case 3: + case 4: + return R.id.latest_small_tile; + + case 0: + default: + return R.id.latest_regular_list; + } + } + } + + public int getSpanSize(int position) { + int relativePositionInCycle = position % 5; + if (relativePositionInCycle == 0) { + return 2; + } else { + return 1; + } + } + + /** + * Applies padding to items, ensuring that the spacing on the left, centre, and right all match. + * The vertical padding is slightly shorter than the horizontal padding also. + * + * @see org.fdroid.fdroid.R.dimen#latest__padding__app_card__horizontal + * @see org.fdroid.fdroid.R.dimen#latest__padding__app_card__vertical + */ + private static class ItemDecorator extends RecyclerView.ItemDecoration { + private final Context context; + + ItemDecorator(Context context) { + this.context = context.getApplicationContext(); + } + + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, RecyclerView parent, + @NonNull RecyclerView.State state) { + int position = parent.getChildAdapterPosition(view); + Resources resources = context.getResources(); + int horizontalPadding = (int) resources.getDimension(R.dimen.latest__padding__app_card__horizontal); + int verticalPadding = (int) resources.getDimension(R.dimen.latest__padding__app_card__vertical); + + int relativePositionInCycle = position % 5; + if (position == 0) { + outRect.set(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); + } else if (relativePositionInCycle != 0) { + // The item on the left will have both left and right padding. The item on the right + // will only have padding on the right. This will allow the same amount of padding + // on the left, centre, and right of the grid, rather than double the padding in the + // middle (which would happen if both left and right padding was set for both items). + boolean isLtr = ViewCompat.getLayoutDirection(parent) == ViewCompat.LAYOUT_DIRECTION_LTR; + boolean isAtStart = relativePositionInCycle == 1 || relativePositionInCycle == 3; + int paddingStart = isAtStart ? horizontalPadding : 0; + int paddingLeft = isLtr ? paddingStart : horizontalPadding; + int paddingRight = isLtr ? horizontalPadding : paddingStart; + outRect.set(paddingLeft, 0, paddingRight, verticalPadding); + } else { + outRect.set(horizontalPadding, 0, horizontalPadding, verticalPadding); + } + } + } +} diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/LatestViewBinder.java b/app/src/main/java/org/fdroid/fdroid/views/main/LatestViewBinder.java index a505955a1..1690a3190 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/LatestViewBinder.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/LatestViewBinder.java @@ -72,7 +72,7 @@ class LatestViewBinder implements Observer>, ChangeListene latestAdapter = new LatestAdapter(activity); GridLayoutManager layoutManager = new GridLayoutManager(activity, 2); - layoutManager.setSpanSizeLookup(new LatestAdapter.SpanSizeLookup()); + layoutManager.setSpanSizeLookup(latestAdapter.getSpanSizeLookup()); emptyState = latestView.findViewById(R.id.empty_state);