Improve grid span count calculation

This commit is contained in:
seven332 committed 2016-03-17 18:35:53 +08:00
1 parent 644113ba56
commit fb4c79a722
11 files changed
+229 -75

No files matched your search

@@ -26,7 +26,6 @@ import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Spannable;
@@ -75,6 +74,7 @@ import com.hippo.util.DrawableManager;
import com.hippo.widget.ContentLayout;
import com.hippo.widget.FabLayout;
import com.hippo.widget.SearchBarMover;
import com.hippo.widget.recyclerview.GridAutoSpanLayoutManager;
import com.hippo.widget.refreshlayout.RefreshLayout;
import com.hippo.yorozuya.ObjectUtils;
import com.hippo.yorozuya.SimpleHandler;
@@ -255,7 +255,7 @@ public class FavoritesScene extends BaseScene implements
contentLayout.setHelper(mHelper);
contentLayout.getFastScroller().setOnDragHandlerListener(this);
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 1);
GridAutoSpanLayoutManager layoutManager = new GridAutoSpanLayoutManager(getContext(), 0);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setSelector(RippleSalon.generateRippleDrawable(false));
mRecyclerView.setDrawSelectorOnTop(true);
@@ -931,7 +931,7 @@ public class FavoritesScene extends BaseScene implements
private class FavoritesAdapter extends GalleryAdapter {
public FavoritesAdapter(LayoutInflater inflater, Context context,
RecyclerView recyclerView, GridLayoutManager layoutManager, int type) {
RecyclerView recyclerView, GridAutoSpanLayoutManager layoutManager, int type) {
super(inflater, context, recyclerView, layoutManager, type);
}
@@ -23,7 +23,6 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -39,7 +38,7 @@ import com.hippo.ehviewer.client.EhCacheKeyFactory;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.ehviewer.client.data.GalleryInfo;
import com.hippo.util.ApiHelper;
import com.hippo.util.LayoutUtils2;
import com.hippo.widget.recyclerview.GridAutoSpanLayoutManager;
import com.hippo.yorozuya.Messenger;
import java.lang.annotation.Retention;
@@ -59,12 +58,12 @@ abstract class GalleryAdapter extends RecyclerView.Adapter<GalleryHolder> implem
private final Context mContext;
private final Resources mResources;
private final RecyclerView mRecyclerView;
private final GridLayoutManager mLayoutManager;
private final GridAutoSpanLayoutManager mLayoutManager;
private RecyclerView.ItemDecoration mGirdDecoration;
private int mType = TYPE_INVALID;
public GalleryAdapter(LayoutInflater inflater, Context context,
RecyclerView recyclerView, GridLayoutManager layoutManager, int type) {
RecyclerView recyclerView, GridAutoSpanLayoutManager layoutManager, int type) {
mInflater = inflater;
mContext = context;
mResources = context.getResources();
@@ -90,9 +89,9 @@ abstract class GalleryAdapter extends RecyclerView.Adapter<GalleryHolder> implem
switch (type) {
default:
case GalleryAdapter.TYPE_LIST: {
int minWidth = mResources.getDimensionPixelOffset(R.dimen.gallery_list_min_width);
int spanCount = LayoutUtils2.calculateSpanCount(mContext, minWidth);
mLayoutManager.setSpanCount(spanCount);
int columnWidth = mResources.getDimensionPixelOffset(R.dimen.gallery_list_column_width);
mLayoutManager.setColumnSize(columnWidth);
mLayoutManager.setStrategy(GridAutoSpanLayoutManager.STRATEGY_MIN_SIZE);
if (null != mGirdDecoration) {
mRecyclerView.removeItemDecoration(mGirdDecoration);
}
@@ -100,9 +99,9 @@ abstract class GalleryAdapter extends RecyclerView.Adapter<GalleryHolder> implem
break;
}
case GalleryAdapter.TYPE_GRID: {
int minWidth = mResources.getDimensionPixelOffset(R.dimen.gallery_grid_min_width);
int spanCount = LayoutUtils2.calculateSpanCount(mContext, minWidth);
mLayoutManager.setSpanCount(spanCount);
int columnWidth = mResources.getDimensionPixelOffset(R.dimen.gallery_grid_column_width);
mLayoutManager.setColumnSize(columnWidth);
mLayoutManager.setStrategy(GridAutoSpanLayoutManager.STRATEGY_SUITABLE_SIZE);
if (null == mGirdDecoration) {
mGirdDecoration = new MarginItemDecoration(
mResources.getDimensionPixelOffset(R.dimen.list_content_interval));
@@ -87,14 +87,13 @@ import com.hippo.util.ActivityHelper;
import com.hippo.util.ApiHelper;
import com.hippo.util.DrawableManager;
import com.hippo.util.ExceptionUtils;
import com.hippo.util.LayoutUtils2;
import com.hippo.util.ReadableTime;
import com.hippo.view.ViewTransition;
import com.hippo.widget.AutoWrapLayout;
import com.hippo.widget.LoadImageView;
import com.hippo.widget.ProgressView;
import com.hippo.widget.ProgressiveRatingBar;
import com.hippo.widget.SimpleGridLayout;
import com.hippo.widget.recyclerview.SimpleGridAutoSpanLayout;
import com.hippo.yorozuya.SimpleHandler;
import com.hippo.yorozuya.ViewUtils;
@@ -208,7 +207,7 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
@Nullable
private View mPreviews;
@Nullable
private SimpleGridLayout mGridLayout;
private SimpleGridAutoSpanLayout mGridLayout;
@Nullable
private TextView mPreviewText;
// Progress
@@ -462,7 +461,7 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
mComments.setOnClickListener(this);
mPreviews = ViewUtils.$$(belowHeader, R.id.previews);
mGridLayout = (SimpleGridLayout) ViewUtils.$$(mPreviews, R.id.grid_layout);
mGridLayout = (SimpleGridAutoSpanLayout) ViewUtils.$$(mPreviews, R.id.grid_layout);
mPreviewText = (TextView) ViewUtils.$$(mPreviews, R.id.preview_text);
RippleSalon.addRipple(mPreviews, false);
mPreviews.setOnClickListener(this);
@@ -849,10 +848,9 @@ public class GalleryDetailScene extends BaseScene implements View.OnClickListene
mPreviewText.setText(R.string.more_previews);
}
int minWidth = getResources().getDimensionPixelOffset(R.dimen.preview_grid_min_width);
int spanCount = LayoutUtils2.calculateSpanCount(getContext(), minWidth);
mGridLayout.setColumnCount(spanCount);
int columnWidth = getResources().getDimensionPixelOffset(R.dimen.preview_grid_column_width);
mGridLayout.setColumnSize(columnWidth);
mGridLayout.setStrategy(SimpleGridAutoSpanLayout.STRATEGY_SUITABLE_SIZE);
LayoutInflater inflater = getActivity().getLayoutInflater();
for (int i = 0, size = previewSet.size(); i < size; i++) {
View view = inflater.inflate(R.layout.item_gallery_preview, mGridLayout, false);
@@ -29,7 +29,6 @@ import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Spannable;
@@ -79,6 +78,7 @@ import com.hippo.util.DrawableManager;
import com.hippo.view.ViewTransition;
import com.hippo.widget.ContentLayout;
import com.hippo.widget.SearchBarMover;
import com.hippo.widget.recyclerview.GridAutoSpanLayoutManager;
import com.hippo.widget.refreshlayout.RefreshLayout;
import com.hippo.yorozuya.AnimationUtils;
import com.hippo.yorozuya.MathUtils;
@@ -355,7 +355,7 @@ public final class GalleryListScene extends BaseScene
contentLayout.setHelper(mHelper);
contentLayout.getFastScroller().setOnDragHandlerListener(this);
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 1);
GridAutoSpanLayoutManager layoutManager = new GridAutoSpanLayoutManager(getContext(), 0);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setSelector(RippleSalon.generateRippleDrawable(false));
mRecyclerView.setDrawSelectorOnTop(true);
@@ -946,7 +946,7 @@ public final class GalleryListScene extends BaseScene
private class GalleryListAdapter extends GalleryAdapter {
public GalleryListAdapter(LayoutInflater inflater, Context context,
RecyclerView recyclerView, GridLayoutManager layoutManager, int type) {
RecyclerView recyclerView, GridAutoSpanLayoutManager layoutManager, int type) {
super(inflater, context, recyclerView, layoutManager, type);
}
@@ -25,7 +25,6 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -49,10 +48,10 @@ import com.hippo.ehviewer.client.exception.EhException;
import com.hippo.ehviewer.ui.GalleryActivity;
import com.hippo.scene.SceneFragment;
import com.hippo.scene.StageActivity;
import com.hippo.util.LayoutUtils2;
import com.hippo.widget.ContentLayout;
import com.hippo.widget.LoadImageView;
import com.hippo.widget.Slider;
import com.hippo.widget.recyclerview.GridAutoSpanLayoutManager;
import com.hippo.yorozuya.LayoutUtils;
import com.hippo.yorozuya.SimpleHandler;
@@ -133,9 +132,10 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
mAdapter = new GalleryPreviewAdapter();
recyclerView.setAdapter(mAdapter);
int minWidth = getResources().getDimensionPixelOffset(R.dimen.preview_grid_min_width);
int spanCount = LayoutUtils2.calculateSpanCount(getContext(), minWidth);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), spanCount));
int columnWidth = getResources().getDimensionPixelOffset(R.dimen.preview_grid_column_width);
GridAutoSpanLayoutManager layoutManager = new GridAutoSpanLayoutManager(getContext(), columnWidth);
layoutManager.setStrategy(GridAutoSpanLayoutManager.STRATEGY_SUITABLE_SIZE);
recyclerView.setLayoutManager(layoutManager);
int padding = LayoutUtils.dp2pix(getContext(), 4);
recyclerView.setPadding(padding, padding, padding, padding);
recyclerView.setClipToPadding(false);
@@ -22,7 +22,6 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -47,6 +46,7 @@ import com.hippo.scene.StageActivity;
import com.hippo.util.ApiHelper;
import com.hippo.util.DrawableManager;
import com.hippo.view.ViewTransition;
import com.hippo.widget.recyclerview.GridAutoSpanLayoutManager;
import com.hippo.yorozuya.ResourcesUtils;
import com.hippo.yorozuya.ViewUtils;
@@ -87,7 +87,7 @@ public class HistoryScene extends ToolbarScene
tip.setCompoundDrawables(null, drawable, null, null);
mList = EhDB.getHistoryLazyList();
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 1);
GridAutoSpanLayoutManager layoutManager = new GridAutoSpanLayoutManager(getContext(), 0);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setSelector(RippleSalon.generateRippleDrawable(false));
recyclerView.setDrawSelectorOnTop(true);
@@ -191,7 +191,7 @@ public class HistoryScene extends ToolbarScene
private class HistoryAdapter extends GalleryAdapter {
public HistoryAdapter(LayoutInflater inflater, Context context,
RecyclerView recyclerView, GridLayoutManager layoutManager, int type) {
RecyclerView recyclerView, GridAutoSpanLayoutManager layoutManager, int type) {
super(inflater, context, recyclerView, layoutManager, type);
}
@@ -1,39 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.util;
import android.content.Context;
import android.graphics.Point;
import android.view.Display;
import android.view.WindowManager;
import com.hippo.yorozuya.MathUtils;
public final class LayoutUtils2 {
private static final Point sPoint = new Point();
private LayoutUtils2() {}
public static int calculateSpanCount(Context context, int minWidth) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
display.getSize(sPoint);
int width = sPoint.x;
return MathUtils.clamp(width / minWidth, 1, Integer.MAX_VALUE);
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.widget.recyclerview;
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
public class GridAutoSpanLayoutManager extends GridLayoutManager {
public static final int STRATEGY_MIN_SIZE = 0;
public static final int STRATEGY_SUITABLE_SIZE = 1;
private int mColumnSize = -1;
private boolean mColumnSizeChanged = true;
private int mStrategy;
public GridAutoSpanLayoutManager(Context context, int columnSize) {
super(context, 1);
setColumnSize(columnSize);
}
public GridAutoSpanLayoutManager(Context context, int columnSize, int orientation, boolean reverseLayout) {
super(context, 1, orientation, reverseLayout);
setColumnSize(columnSize);
}
public void setColumnSize(int columnSize) {
if (columnSize == mColumnSize) {
return;
}
mColumnSize = columnSize;
mColumnSizeChanged = true;
}
public void setStrategy(int strategy) {
if (strategy == mStrategy) {
return;
}
mStrategy = strategy;
mColumnSizeChanged = true;
}
public static int getSpanCountForSuitableSize(int total, int single) {
int span = total / single;
if (span <= 0) {
return 1;
}
int span2 = span + 1;
float deviation = Math.abs(1 - (total / span / (float) single));
float deviation2 = Math.abs(1 - (total / span2 / (float) single));
return deviation < deviation2 ? span : span2;
}
public static int getSpanCountForMinSize(int total, int single) {
return Math.max(1, total / single);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
if (mColumnSizeChanged && mColumnSize > 0) {
int totalSpace;
if (getOrientation() == VERTICAL) {
totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
} else {
totalSpace = getHeight() - getPaddingTop() - getPaddingBottom();
}
int spanCount;
switch (mStrategy) {
default:
case STRATEGY_MIN_SIZE:
spanCount = getSpanCountForMinSize(totalSpace, mColumnSize);
break;
case STRATEGY_SUITABLE_SIZE:
spanCount = getSpanCountForSuitableSize(totalSpace, mColumnSize);
break;
}
setSpanCount(spanCount);
mColumnSizeChanged = false;
}
super.onLayoutChildren(recycler, state);
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.widget.recyclerview;
import android.content.Context;
import android.util.AttributeSet;
import com.hippo.widget.SimpleGridLayout;
public class SimpleGridAutoSpanLayout extends SimpleGridLayout {
public static final int STRATEGY_MIN_SIZE = 0;
public static final int STRATEGY_SUITABLE_SIZE = 1;
private int mColumnSize = -1;
private boolean mColumnSizeChanged = true;
private int mStrategy;
public SimpleGridAutoSpanLayout(Context context) {
super(context);
}
public SimpleGridAutoSpanLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SimpleGridAutoSpanLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setColumnSize(int columnSize) {
if (columnSize == mColumnSize) {
return;
}
mColumnSize = columnSize;
mColumnSizeChanged = true;
}
public void setStrategy(int strategy) {
if (strategy == mStrategy) {
return;
}
mStrategy = strategy;
mColumnSizeChanged = true;
}
public static int getSpanCountForSuitableSize(int total, int single) {
int span = total / single;
if (span <= 0) {
return 1;
}
int span2 = span + 1;
float deviation = Math.abs(1 - (total / span / (float) single));
float deviation2 = Math.abs(1 - (total / span2 / (float) single));
return deviation < deviation2 ? span : span2;
}
public static int getSpanCountForMinSize(int total, int single) {
return Math.max(1, total / single);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (mColumnSizeChanged && mColumnSize > 0 && widthMode == MeasureSpec.EXACTLY) {
int totalSpace = widthSize - getPaddingRight() - getPaddingLeft();
int spanCount;
switch (mStrategy) {
default:
case STRATEGY_MIN_SIZE:
spanCount = getSpanCountForMinSize(totalSpace, mColumnSize);
break;
case STRATEGY_SUITABLE_SIZE:
spanCount = getSpanCountForSuitableSize(totalSpace, mColumnSize);
break;
}
setColumnCount(spanCount);
mColumnSizeChanged = false;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}