/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.litho.widget;
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import com.facebook.litho.ComponentInfo;
import com.facebook.litho.SizeSpec;
import static com.facebook.litho.SizeSpec.EXACTLY;
import static com.facebook.litho.SizeSpec.UNSPECIFIED;
public class GridLayoutInfo implements LayoutInfo {
private final GridLayoutManager mGridLayoutManager;
private final GridSpanSizeLookup mGridSpanSizeLookup;
private ComponentInfoCollection mComponentInfoCollection;
public GridLayoutInfo(Context context, int spanCount, int orientation, boolean reverseLayout) {
mGridLayoutManager = new GridLayoutManager(context, spanCount, orientation, reverseLayout);
mGridSpanSizeLookup = new GridSpanSizeLookup();
mGridLayoutManager.setSpanSizeLookup(mGridSpanSizeLookup);
}
public GridLayoutInfo(Context context, int spanCount) {
this(context, spanCount, OrientationHelper.VERTICAL, false);
}
@Override
public int getScrollDirection() {
return mGridLayoutManager.getOrientation();
}
@Override
public int findFirstVisiblePosition() {
return mGridLayoutManager.findFirstVisibleItemPosition();
}
@Override
public int findLastVisiblePosition() {
return mGridLayoutManager.findLastVisibleItemPosition();
}
@Override
public RecyclerView.LayoutManager getLayoutManager() {
return mGridLayoutManager;
}
@Override
public void setComponentInfoCollection(ComponentInfoCollection componentInfoCollection) {
mComponentInfoCollection = componentInfoCollection;
}
@Override
public int approximateRangeSize(
int firstMeasuredItemWidth,
int firstMeasuredItemHeight,
int recyclerMeasuredWidth,
int recyclerMeasuredHeight) {
final int spanCount = mGridLayoutManager.getSpanCount();
switch (mGridLayoutManager.getOrientation()) {
case GridLayoutManager.HORIZONTAL:
final int colCount = (int) Math.ceil(
(double) recyclerMeasuredWidth / (double) firstMeasuredItemWidth);
return colCount * spanCount;
default:
final int rowCount = (int) Math.ceil(
(double) recyclerMeasuredHeight / (double) firstMeasuredItemHeight);
return rowCount * spanCount;
}
}
/**
* @param widthSpec the widthSpec used to measure the parent {@link RecyclerSpec}.
* @return widthSpec of a child that is of span size 1
*/
@Override
public int getChildWidthSpec(int widthSpec, ComponentInfo componentInfo) {
switch (mGridLayoutManager.getOrientation()) {
case GridLayoutManager.HORIZONTAL:
return SizeSpec.makeSizeSpec(0, UNSPECIFIED);
default:
final int spanCount = mGridLayoutManager.getSpanCount();
final int spanSize = componentInfo.getSpanSize();
return spanSize * SizeSpec.makeSizeSpec(SizeSpec.getSize(widthSpec) / spanCount, EXACTLY);
}
}
/**
* @param heightSpec the heightSpec used to measure the parent {@link RecyclerSpec}.
* @return heightSpec of a child that is of span size 1
*/
@Override
public int getChildHeightSpec(int heightSpec, ComponentInfo componentInfo) {
switch (mGridLayoutManager.getOrientation()) {
case GridLayoutManager.HORIZONTAL:
final int spanCount = mGridLayoutManager.getSpanCount();
final int spanSize = componentInfo.getSpanSize();
return spanSize * SizeSpec.makeSizeSpec(SizeSpec.getSize(heightSpec) / spanCount, EXACTLY);
default:
return SizeSpec.makeSizeSpec(0, UNSPECIFIED);
}
}
private class GridSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
@Override
public int getSpanSize(int position) {
if (mComponentInfoCollection == null) {
return 1;
}
return mComponentInfoCollection.getComponentInfoAt(position).getSpanSize();
}
}
}