提交 add9faf3 编写于 作者: T Takeshi Hagikura 提交者: Takeshi Hagikura

Implement incremental calculation for the flex lines. (#151)

In the RecyclerView, only the visible part of the RecyclerView is necessary
to be rendered. Thus, not all the flex items need to be measured at first.
This PR makes the flex lines to be calculated only the visible part.

Also this PR removes the support for the order attribute from the FlexboxLayoutManger because calculating the order requires all view to be inflated at least once, which may lead to bad performance if there is a large number of items in the adapter.
上级 bd590945
...@@ -30,6 +30,7 @@ import android.view.View; ...@@ -30,6 +30,7 @@ import android.view.View;
import static com.google.android.flexbox.test.IsEqualAllowingError.isEqualAllowingError; import static com.google.android.flexbox.test.IsEqualAllowingError.isEqualAllowingError;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
...@@ -77,6 +78,7 @@ public class FlexboxHelperTest { ...@@ -77,6 +78,7 @@ public class FlexboxHelperTest {
int heightMeasureSpec = View.MeasureSpec int heightMeasureSpec = View.MeasureSpec
.makeMeasureSpec(1000, View.MeasureSpec.UNSPECIFIED); .makeMeasureSpec(1000, View.MeasureSpec.UNSPECIFIED);
mFlexboxHelper.ensureIndexToFlexLine(mFlexContainer.getFlexItemCount());
FlexboxHelper.FlexLinesResult result = mFlexboxHelper FlexboxHelper.FlexLinesResult result = mFlexboxHelper
.calculateHorizontalFlexLines(widthMeasureSpec, heightMeasureSpec); .calculateHorizontalFlexLines(widthMeasureSpec, heightMeasureSpec);
...@@ -88,10 +90,11 @@ public class FlexboxHelperTest { ...@@ -88,10 +90,11 @@ public class FlexboxHelperTest {
assertEquals(100, result.mFlexLines.get(1).getCrossSize()); assertEquals(100, result.mFlexLines.get(1).getCrossSize());
assertEquals(100, result.mFlexLines.get(2).getCrossSize()); assertEquals(100, result.mFlexLines.get(2).getCrossSize());
assertEquals(0, mFlexboxHelper.mIndexToFlexLine.get(0)); assertNotNull(mFlexboxHelper.mIndexToFlexLine);
assertEquals(0, mFlexboxHelper.mIndexToFlexLine.get(1)); assertEquals(0, mFlexboxHelper.mIndexToFlexLine[0]);
assertEquals(1, mFlexboxHelper.mIndexToFlexLine.get(2)); assertEquals(0, mFlexboxHelper.mIndexToFlexLine[1]);
assertEquals(2, mFlexboxHelper.mIndexToFlexLine.get(3)); assertEquals(1, mFlexboxHelper.mIndexToFlexLine[2]);
assertEquals(2, mFlexboxHelper.mIndexToFlexLine[3]);
} }
@Test @Test
...@@ -118,6 +121,7 @@ public class FlexboxHelperTest { ...@@ -118,6 +121,7 @@ public class FlexboxHelperTest {
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.UNSPECIFIED); int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.UNSPECIFIED);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.EXACTLY); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.EXACTLY);
mFlexboxHelper.ensureIndexToFlexLine(mFlexContainer.getFlexItemCount());
FlexboxHelper.FlexLinesResult result = mFlexboxHelper FlexboxHelper.FlexLinesResult result = mFlexboxHelper
.calculateVerticalFlexLines(widthMeasureSpec, heightMeasureSpec); .calculateVerticalFlexLines(widthMeasureSpec, heightMeasureSpec);
...@@ -129,10 +133,11 @@ public class FlexboxHelperTest { ...@@ -129,10 +133,11 @@ public class FlexboxHelperTest {
assertEquals(100, result.mFlexLines.get(1).getCrossSize()); assertEquals(100, result.mFlexLines.get(1).getCrossSize());
assertEquals(100, result.mFlexLines.get(2).getCrossSize()); assertEquals(100, result.mFlexLines.get(2).getCrossSize());
assertEquals(0, mFlexboxHelper.mIndexToFlexLine.get(0)); assertNotNull(mFlexboxHelper.mIndexToFlexLine);
assertEquals(0, mFlexboxHelper.mIndexToFlexLine.get(1)); assertEquals(0, mFlexboxHelper.mIndexToFlexLine[0]);
assertEquals(1, mFlexboxHelper.mIndexToFlexLine.get(2)); assertEquals(0, mFlexboxHelper.mIndexToFlexLine[1]);
assertEquals(2, mFlexboxHelper.mIndexToFlexLine.get(3)); assertEquals(1, mFlexboxHelper.mIndexToFlexLine[2]);
assertEquals(2, mFlexboxHelper.mIndexToFlexLine[3]);
} }
@Test @Test
......
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
~ See the License for the specific language governing permissions and ~ See the License for the specific language governing permissions and
~ limitations under the License. ~ limitations under the License.
--> -->
<!-- Some APIs in espresso requires the view being performed is at least 90% visible to the
user, using the small width so that low resolution devices are covered-->
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="400dp" android:layout_width="320dp"
android:layout_height="300dp" /> android:layout_height="240dp" />
...@@ -25,6 +25,7 @@ import android.os.Parcelable; ...@@ -25,6 +25,7 @@ import android.os.Parcelable;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
...@@ -172,6 +173,20 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer { ...@@ -172,6 +173,20 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer {
/** The width of the {@link #mDividerDrawableVertical}. */ /** The width of the {@link #mDividerDrawableVertical}. */
private int mDividerVerticalWidth; private int mDividerVerticalWidth;
/**
* Holds reordered indices, which {@link FlexItem#getOrder()} parameters are taken
* into account
*/
private int[] mReorderedIndices;
/**
* Caches the {@link FlexItem#getOrder()} attributes for children views.
* Key: the index of the view reordered indices using the {@link FlexItem#getOrder()}
* isn't taken into account)
* Value: the value for the order attribute
*/
private SparseIntArray mOrderCache;
private FlexboxHelper mFlexboxHelper = new FlexboxHelper(this); private FlexboxHelper mFlexboxHelper = new FlexboxHelper(this);
private List<FlexLine> mFlexLines = new ArrayList<>(); private List<FlexLine> mFlexLines = new ArrayList<>();
...@@ -233,8 +248,11 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer { ...@@ -233,8 +248,11 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mFlexboxHelper.isOrderChangedFromLastMeasurement()) { if (mOrderCache == null) {
mFlexboxHelper.mReorderedIndices = mFlexboxHelper.createReorderedIndices(); mOrderCache = new SparseIntArray(getChildCount());
}
if (mFlexboxHelper.isOrderChangedFromLastMeasurement(mOrderCache)) {
mReorderedIndices = mFlexboxHelper.createReorderedIndices(mOrderCache);
} }
// TODO: Only calculate the children views which are affected from the last measure. // TODO: Only calculate the children views which are affected from the last measure.
...@@ -274,10 +292,10 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer { ...@@ -274,10 +292,10 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer {
* returns {@code null}. * returns {@code null}.
*/ */
public View getReorderedChildAt(int index) { public View getReorderedChildAt(int index) {
if (index < 0 || index >= mFlexboxHelper.mReorderedIndices.length) { if (index < 0 || index >= mReorderedIndices.length) {
return null; return null;
} }
return getChildAt(mFlexboxHelper.mReorderedIndices[index]); return getChildAt(mReorderedIndices[index]);
} }
@Override @Override
...@@ -287,12 +305,15 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer { ...@@ -287,12 +305,15 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer {
@Override @Override
public void addView(View child, int index, ViewGroup.LayoutParams params) { public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (mOrderCache == null) {
mOrderCache = new SparseIntArray(getChildCount());
}
// Create an array for the reordered indices before the View is added in the parent // Create an array for the reordered indices before the View is added in the parent
// ViewGroup since otherwise reordered indices won't be in effect before the // ViewGroup since otherwise reordered indices won't be in effect before the
// FlexboxLayout's onMeasure is called. // FlexboxLayout's onMeasure is called.
// Because requestLayout is requested in the super.addView method. // Because requestLayout is requested in the super.addView method.
mFlexboxHelper.mReorderedIndices = mFlexboxHelper mReorderedIndices = mFlexboxHelper
.createReorderedIndices(child, index, params); .createReorderedIndices(child, index, params, mOrderCache);
super.addView(child, index, params); super.addView(child, index, params);
} }
......
...@@ -217,6 +217,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -217,6 +217,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
if (mFlexDirection != flexDirection) { if (mFlexDirection != flexDirection) {
mFlexDirection = flexDirection; mFlexDirection = flexDirection;
mOrientationHelper = null; mOrientationHelper = null;
mFlexLines.clear();
requestLayout(); requestLayout();
} }
} }
...@@ -232,6 +233,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -232,6 +233,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
if (mFlexWrap != flexWrap) { if (mFlexWrap != flexWrap) {
mFlexWrap = flexWrap; mFlexWrap = flexWrap;
mOrientationHelper = null; mOrientationHelper = null;
mFlexLines.clear();
requestLayout(); requestLayout();
} }
} }
...@@ -260,6 +262,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -260,6 +262,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
public void setAlignItems(@AlignItems int alignItems) { public void setAlignItems(@AlignItems int alignItems) {
if (mAlignItems != alignItems) { if (mAlignItems != alignItems) {
mAlignItems = alignItems; mAlignItems = alignItems;
mFlexLines.clear();
requestLayout(); requestLayout();
} }
} }
...@@ -274,6 +277,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -274,6 +277,7 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
public void setAlignContent(@AlignContent int alignContent) { public void setAlignContent(@AlignContent int alignContent) {
if (mAlignContent != alignContent) { if (mAlignContent != alignContent) {
mAlignContent = alignContent; mAlignContent = alignContent;
mFlexLines.clear();
requestLayout(); requestLayout();
} }
} }
...@@ -337,19 +341,22 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -337,19 +341,22 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
} }
/** /**
* Returns a View, which is reordered by taking {@link LayoutParams#mOrder} parameters * Returns a View for the given index.
* into account. * The order attribute ({@link FlexItem#getOrder()}) is not supported by this class since
* otherwise all view holders need to be inflated at least once even though only the visible
* part of the layout is needed.
* Implementing just to conform the {@link FlexContainer} interface.
* *
* @param index the index of the view * @param index the index of the view
* @return the reordered view, which {@link LayoutParams@mOrder} is taken into account. * @return the view for the given index.
* If the index is negative or out of bounds of the number of contained views, * If the index is negative or out of bounds of the number of contained views,
* returns {@code null}. * returns {@code null}.
*/ */
public View getReorderedChildAt(int index) { public View getReorderedChildAt(int index) {
if (index < 0 || index >= mFlexboxHelper.mReorderedIndices.length) { if (index < 0 || index >= mState.getItemCount()) {
return null; return null;
} }
return mRecycler.getViewForPosition(mFlexboxHelper.mReorderedIndices[index]); return mRecycler.getViewForPosition(index);
} }
@Override @Override
...@@ -447,38 +454,67 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -447,38 +454,67 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
ensureOrientationHelper(); ensureOrientationHelper();
ensureLayoutState(); ensureLayoutState();
mFlexboxHelper.ensureMeasureSpecCache(childCount); mFlexboxHelper.ensureMeasureSpecCache(childCount);
mFlexboxHelper.ensureIndexToFlexLine(childCount);
mLayoutState.mShouldRecycle = false; mLayoutState.mShouldRecycle = false;
mAnchorInfo.reset(); mAnchorInfo.reset();
updateAnchorInfoForLayout(state, mAnchorInfo); updateAnchorInfoForLayout(state, mAnchorInfo);
// TODO: If we support the order attribute, we need to inflate the all ViewHolders in the // Unlike the FlexboxLayout, the order attribute is not supported, we don't calculated the
// adapter instead of inflating only the visible ViewHolders, which is inefficient given // order attribute because preparing the order attribute requires all
// that this is part of RecyclerView // view holders to be inflated at least once, which is inefficient if the number of items
if (mFlexboxHelper.isOrderChangedFromLastMeasurement()) { // is large
mFlexboxHelper.mReorderedIndices = mFlexboxHelper.createReorderedIndices();
} resolveLayoutDirection();
updateLayoutStateToFillEnd(mAnchorInfo);
// Calculate the flex lines until the calculated cross size reaches the
// LayoutState#mAvailable (or until the end of the flex container)
//noinspection ResourceType //noinspection ResourceType
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(getWidth(), getWidthMode()); int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(getWidth(), getWidthMode());
//noinspection ResourceType //noinspection ResourceType
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(getHeight(), getHeightMode()); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(getHeight(), getHeightMode());
FlexboxHelper.FlexLinesResult flexLinesResult; FlexboxHelper.FlexLinesResult flexLinesResult;
mFlexLines.clear();
// TODO: Change the code to calculate only the visible area
int paddingAlongCrossAxis;
if (isMainAxisDirectionHorizontal()) { if (isMainAxisDirectionHorizontal()) {
flexLinesResult = mFlexboxHelper if (mFlexLines.size() > 0) {
.calculateHorizontalFlexLines(widthMeasureSpec, heightMeasureSpec); // Remove the already calculated flex lines from the anchor position and
paddingAlongCrossAxis = getPaddingTop() + getPaddingBottom(); // calculate beyond the available amount (visible area that needs to be filled)
mFlexboxHelper.clearFlexLines(mFlexLines, mAnchorInfo.mPosition);
flexLinesResult = mFlexboxHelper
.calculateHorizontalFlexLines(widthMeasureSpec, heightMeasureSpec,
mLayoutState.mAvailable, mAnchorInfo.mPosition, mFlexLines);
} else {
mFlexboxHelper.ensureIndexToFlexLine(childCount);
flexLinesResult = mFlexboxHelper
.calculateHorizontalFlexLines(widthMeasureSpec, heightMeasureSpec,
mLayoutState.mAvailable);
}
} else { } else {
flexLinesResult = mFlexboxHelper if (mFlexLines.size() > 0) {
.calculateVerticalFlexLines(widthMeasureSpec, heightMeasureSpec); // Remove the already calculated flex lines from the anchor position and
paddingAlongCrossAxis = getPaddingLeft() + getPaddingRight(); // calculate beyond the available amount (visible area that needs to be filled)
mFlexboxHelper.clearFlexLines(mFlexLines, mAnchorInfo.mPosition);
flexLinesResult = mFlexboxHelper
.calculateVerticalFlexLines(widthMeasureSpec, heightMeasureSpec,
mLayoutState.mAvailable, mAnchorInfo.mPosition, mFlexLines);
} else {
mFlexboxHelper.ensureIndexToFlexLine(childCount);
flexLinesResult = mFlexboxHelper
.calculateVerticalFlexLines(widthMeasureSpec, heightMeasureSpec,
mLayoutState.mAvailable);
}
} }
mFlexLines = flexLinesResult.mFlexLines; mFlexLines = flexLinesResult.mFlexLines;
mFlexboxHelper.determineMainSize(widthMeasureSpec, heightMeasureSpec); mFlexboxHelper.determineMainSize(widthMeasureSpec, heightMeasureSpec,
mAnchorInfo.mPosition);
// Unlike the FlexboxLayout not calling FlexboxHelper#determineCrossSize because
// the align content attribute (which is used to determine the cross size) is only effective
// when the size of flex line is equal or more than 2 and the parent height
// (length along the cross size) is fixed. But in RecyclerView, these two conditions can't
// be true at the same time. Because it's scrollable along the cross axis
// or even if not (when flex wrap is "nowrap") the size of the flex lines should be 1.
mFlexboxHelper.stretchViews(mAnchorInfo.mPosition);
if (DEBUG) { if (DEBUG) {
for (int i = 0, size = mFlexLines.size(); i < size; i++) { for (int i = 0, size = mFlexLines.size(); i < size; i++) {
FlexLine flexLine = mFlexLines.get(i); FlexLine flexLine = mFlexLines.get(i);
...@@ -487,14 +523,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -487,14 +523,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
flexLine.getItemCount())); flexLine.getItemCount()));
} }
} }
mFlexboxHelper.determineCrossSize(widthMeasureSpec, heightMeasureSpec,
paddingAlongCrossAxis);
mFlexboxHelper.stretchViews();
detachAndScrapAttachedViews(recycler); detachAndScrapAttachedViews(recycler);
resolveLayoutDirection();
updateLayoutStateToFillEnd(mAnchorInfo);
int filledToEnd = fill(recycler, state, mLayoutState); int filledToEnd = fill(recycler, state, mLayoutState);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, String.format("filled: %d toward end", filledToEnd)); Log.d(TAG, String.format("filled: %d toward end", filledToEnd));
...@@ -1104,10 +1134,10 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1104,10 +1134,10 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
} }
/** /**
* @param delta the delta for the amount that is being scrolled * @param delta the delta for the amount that is being scrolled
* (either horizontally or vertically) * (either horizontally or vertically)
* @param recycler the Recycler instance * @param recycler the Recycler instance
* @param state the Recycler.State instance * @param state the Recycler.State instance
* @return the amount actually scrolled * @return the amount actually scrolled
*/ */
private int handleScrolling(int delta, RecyclerView.Recycler recycler, private int handleScrolling(int delta, RecyclerView.Recycler recycler,
...@@ -1134,37 +1164,59 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1134,37 +1164,59 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
} }
private void updateLayoutState(@LayoutDirection int layoutDirection, int absDelta) { private void updateLayoutState(@LayoutDirection int layoutDirection, int absDelta) {
assert mFlexboxHelper.mIndexToFlexLine != null;
// TODO: Consider updating LayoutState#mExtra to support better smooth scrolling // TODO: Consider updating LayoutState#mExtra to support better smooth scrolling
mLayoutState.mLayoutDirection = layoutDirection; mLayoutState.mLayoutDirection = layoutDirection;
if (layoutDirection == LayoutDirection.END) { if (layoutDirection == LayoutDirection.END) {
View lastVisible = getChildAt(getChildCount() - 1); View lastVisible = getChildAt(getChildCount() - 1);
mLayoutState.mItemDirection = ItemDirection.TAIL; mLayoutState.mItemDirection = ItemDirection.TAIL;
mLayoutState.mPosition = getPosition(lastVisible) + mLayoutState.mItemDirection; mLayoutState.mPosition = getPosition(lastVisible) + mLayoutState.mItemDirection;
mLayoutState.mFlexLinePosition = if (mFlexboxHelper.mIndexToFlexLine.length <= mLayoutState.mPosition) {
mFlexboxHelper.mIndexToFlexLine mLayoutState.mFlexLinePosition = NO_POSITION;
.get(mLayoutState.mPosition, 0); } else {
mLayoutState.mFlexLinePosition
= mFlexboxHelper.mIndexToFlexLine[mLayoutState.mPosition];
}
mLayoutState.mOffset = mOrientationHelper.getDecoratedEnd(lastVisible); mLayoutState.mOffset = mOrientationHelper.getDecoratedEnd(lastVisible);
mLayoutState.mScrollingOffset = mOrientationHelper.getDecoratedEnd(lastVisible) mLayoutState.mScrollingOffset = mOrientationHelper.getDecoratedEnd(lastVisible)
- mOrientationHelper.getEndAfterPadding(); - mOrientationHelper.getEndAfterPadding();
// If the RecyclerView tries to scroll beyond the already calculated
// flex container, need to calculate until the amount that needs to be filled
if ((mLayoutState.mFlexLinePosition == NO_POSITION
|| mLayoutState.mFlexLinePosition > mFlexLines.size() - 1) &&
mLayoutState.mPosition <= getFlexItemCount()) {
//noinspection ResourceType
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(getWidth(), getWidthMode());
//noinspection ResourceType
int heightMeasureSpec = View.MeasureSpec
.makeMeasureSpec(getHeight(), getHeightMode());
int needsToFill = absDelta - mLayoutState.mScrollingOffset;
if (needsToFill > 0) {
mFlexboxHelper.calculateHorizontalFlexLines(
widthMeasureSpec, heightMeasureSpec, needsToFill,
mLayoutState.mPosition, mFlexLines);
}
}
} else { } else {
View firstVisible = getChildAt(0); View firstVisible = getChildAt(0);
mLayoutState.mItemDirection = ItemDirection.TAIL; mLayoutState.mItemDirection = ItemDirection.TAIL;
int position = getPosition(firstVisible); int position = getPosition(firstVisible);
FlexLine currentLine = mFlexLines.get(mFlexboxHelper.mIndexToFlexLine.get(position, 0)); int flexLinePosition = mFlexboxHelper.mIndexToFlexLine[position];
if (flexLinePosition == NO_POSITION) {
flexLinePosition = 0;
}
FlexLine currentLine = mFlexLines.get(flexLinePosition);
// The position of the next item toward start should be on the next flex line, // The position of the next item toward start should be on the next flex line,
// shifting the position by the number of the items in the current line. // shifting the position by the number of the items in the current line.
mLayoutState.mPosition = position - currentLine.getItemCount(); mLayoutState.mPosition = position - currentLine.getItemCount();
mLayoutState.mFlexLinePosition = mLayoutState.mFlexLinePosition = flexLinePosition;
mFlexboxHelper.mIndexToFlexLine
.get(mLayoutState.mPosition, 0);
mLayoutState.mOffset = mOrientationHelper.getDecoratedStart(firstVisible); mLayoutState.mOffset = mOrientationHelper.getDecoratedStart(firstVisible);
mLayoutState.mScrollingOffset = -mOrientationHelper.getDecoratedStart(firstVisible) mLayoutState.mScrollingOffset = -mOrientationHelper.getDecoratedStart(firstVisible)
+ mOrientationHelper.getStartAfterPadding(); + mOrientationHelper.getStartAfterPadding();
} }
mLayoutState.mAvailable = absDelta; mLayoutState.mAvailable = absDelta - mLayoutState.mScrollingOffset;
mLayoutState.mAvailable -= mLayoutState.mScrollingOffset;
} }
/** /**
...@@ -1211,11 +1263,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1211,11 +1263,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
*/ */
public static class LayoutParams extends RecyclerView.LayoutParams implements FlexItem { public static class LayoutParams extends RecyclerView.LayoutParams implements FlexItem {
/**
* @see FlexItem#getOrder()
*/
private int mOrder = FlexItem.ORDER_DEFAULT;
/** /**
* @see FlexItem#getFlexGrow() * @see FlexItem#getFlexGrow()
*/ */
...@@ -1415,7 +1462,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1415,7 +1462,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
public LayoutParams(LayoutParams source) { public LayoutParams(LayoutParams source) {
super(source); super(source);
mOrder = source.mOrder;
mFlexGrow = source.mFlexGrow; mFlexGrow = source.mFlexGrow;
mFlexShrink = source.mFlexShrink; mFlexShrink = source.mFlexShrink;
mAlignSelf = source.mAlignSelf; mAlignSelf = source.mAlignSelf;
...@@ -1429,12 +1475,14 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1429,12 +1475,14 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@Override @Override
public int getOrder() { public int getOrder() {
return mOrder; return FlexItem.ORDER_DEFAULT;
} }
@Override @Override
public void setOrder(int order) { public void setOrder(int order) {
mOrder = order; Log.w(TAG, "Setting the order in the "
+ "FlexboxLayoutManager is not supported(ignored). Use FlexboxLayout "
+ "if you need to reorder using the attribute.");
} }
@Override @Override
...@@ -1444,7 +1492,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1444,7 +1492,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.mOrder);
dest.writeFloat(this.mFlexGrow); dest.writeFloat(this.mFlexGrow);
dest.writeFloat(this.mFlexShrink); dest.writeFloat(this.mFlexShrink);
dest.writeInt(this.mAlignSelf); dest.writeInt(this.mAlignSelf);
...@@ -1464,7 +1511,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1464,7 +1511,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
protected LayoutParams(Parcel in) { protected LayoutParams(Parcel in) {
super(WRAP_CONTENT, WRAP_CONTENT); super(WRAP_CONTENT, WRAP_CONTENT);
this.mOrder = in.readInt();
this.mFlexGrow = in.readFloat(); this.mFlexGrow = in.readFloat();
this.mFlexShrink = in.readFloat(); this.mFlexShrink = in.readFloat();
this.mAlignSelf = in.readInt(); this.mAlignSelf = in.readInt();
...@@ -1541,8 +1587,34 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements ...@@ -1541,8 +1587,34 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
} else { } else {
mCoordinate = mOrientationHelper.getDecoratedStart(view); mCoordinate = mOrientationHelper.getDecoratedStart(view);
} }
mPosition = getPosition(view); int position = getPosition(view);
mFlexLinePosition = mFlexboxHelper.mIndexToFlexLine.get(mPosition, 0); // It's likely that the view is the first item in a flex line, but if not get the
// index of the first item in the same line because the calculation of the flex lines
// expects that it starts from the first item in a flex line
mPosition = getFirstItemIndexInLine(position);
assert mFlexboxHelper.mIndexToFlexLine != null;
int flexLinePosition = mFlexboxHelper.mIndexToFlexLine[mPosition];
mFlexLinePosition = flexLinePosition != NO_POSITION ? flexLinePosition : 0;
}
/**
* @param index the index in which the flex is determined
* @return the index of the flex item that is the first item in the same line
*/
private int getFirstItemIndexInLine(int index) {
assert mFlexboxHelper.mIndexToFlexLine != null;
int flexLinePosition = mFlexboxHelper.mIndexToFlexLine[index];
if (index == 0 || mFlexboxHelper.mIndexToFlexLine[index - 1] != flexLinePosition) {
return index;
}
for (int i = index - 1; i > 0; i--) {
int first = mFlexboxHelper.mIndexToFlexLine[i];
int second = mFlexboxHelper.mIndexToFlexLine[i - 1];
if (first != second) {
return first;
}
}
return 0;
} }
@Override @Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册