Skip to content

Fix the issue item decorations are not included for judging if wrapping is required. #541

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2494,6 +2494,68 @@ class FlexboxLayoutManagerTest {
assertThat(view7!!.left, isEqualAllowingError(activity.dpToPixel(200)))
}

@Test
@FlakyTest
@Throws(Throwable::class)
fun testDecoration_length_is_included_in_wrapCondition_direction_row() {
val activity = activityRule.activity
val layoutManager = FlexboxLayoutManager(activity)
val adapter = TestAdapter()
val drawable = ResourcesCompat.getDrawable(activity.resources, R.drawable.divider_thick, null)
val itemDecoration = FlexboxItemDecoration(activity)
itemDecoration.setDrawable(drawable)

activityRule.runOnUiThread {
activity.setContentView(R.layout.recyclerview)
val recyclerView = activity.findViewById<RecyclerView>(R.id.recyclerview)
layoutManager.flexDirection = FlexDirection.ROW
recyclerView.layoutManager = layoutManager
recyclerView.addItemDecoration(itemDecoration)
recyclerView.adapter = adapter

adapter.addItem(createLayoutParams(activity, 90, 110))
adapter.addItem(createLayoutParams(activity, 90, 110))
adapter.addItem(createLayoutParams(activity, 90, 110))
// RecyclerView width: 320, height: 240.
}
InstrumentationRegistry.getInstrumentation().waitForIdleSync()

// Including the length of decorations, the size should be 2
assertThat(layoutManager.flexDirection, `is`(FlexDirection.ROW))
assertThat(layoutManager.flexLines.size, `is`(2))
}

@Test
@FlakyTest
@Throws(Throwable::class)
fun testDecoration_length_is_included_in_wrapCondition_direction_column() {
val activity = activityRule.activity
val layoutManager = FlexboxLayoutManager(activity)
val adapter = TestAdapter()
val drawable = ResourcesCompat.getDrawable(activity.resources, R.drawable.divider_thick, null)
val itemDecoration = FlexboxItemDecoration(activity)
itemDecoration.setDrawable(drawable)

activityRule.runOnUiThread {
activity.setContentView(R.layout.recyclerview)
val recyclerView = activity.findViewById<RecyclerView>(R.id.recyclerview)
layoutManager.flexDirection = FlexDirection.COLUMN
recyclerView.layoutManager = layoutManager
recyclerView.addItemDecoration(itemDecoration)
recyclerView.adapter = adapter

adapter.addItem(createLayoutParams(activity, 100, 68))
adapter.addItem(createLayoutParams(activity, 100, 68))
adapter.addItem(createLayoutParams(activity, 100, 68))
// RecyclerView width: 320, height: 240.
}
InstrumentationRegistry.getInstrumentation().waitForIdleSync()

// Including the length of decorations, the size should be 2
assertThat(layoutManager.flexDirection, `is`(FlexDirection.COLUMN))
assertThat(layoutManager.flexLines.size, `is`(2))
}

@Test
@FlakyTest
@Throws(Throwable::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
private static final String TAG = "FlexboxLayoutManager";

/**
* Temporary Rect instance to be passed to
* {@link RecyclerView.LayoutManager#calculateItemDecorationsForChild}
* Temporary Rect instance to be passed to a method that needs a Rect instance for receiving
* output (e.g.{@link RecyclerView.LayoutManager#calculateItemDecorationsForChild})
* to avoid creating a Rect instance every time.
*/
private static final Rect TEMP_RECT = new Rect();
Expand Down Expand Up @@ -114,6 +114,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
*/
private RecyclerView.Recycler mRecycler;

private RecyclerView mRecyclerView;

/**
* A snapshot of the {@link RecyclerView.State} instance at a given moment.
* It's not guaranteed that this instance has a reference to the latest State.
Expand Down Expand Up @@ -389,20 +391,44 @@ public List<FlexLine> getFlexLines() {

@Override
public int getDecorationLengthMainAxis(View view, int index, int indexInFlexLine) {
int result = 0;
if (isMainAxisDirectionHorizontal()) {
return getLeftDecorationWidth(view) + getRightDecorationWidth(view);
result = result + getLeftDecorationWidth(view) + getRightDecorationWidth(view);
for (int i = 0; i < mRecyclerView.getItemDecorationCount(); i++) {
mRecyclerView.getItemDecorationAt(i).getItemOffsets(
TEMP_RECT, view, mRecyclerView, mState);
result = result + TEMP_RECT.right + TEMP_RECT.left;
}
} else {
return getTopDecorationHeight(view) + getBottomDecorationHeight(view);
result = result + getTopDecorationHeight(view) + getBottomDecorationHeight(view);
for (int i = 0; i < mRecyclerView.getItemDecorationCount(); i++) {
mRecyclerView.getItemDecorationAt(i).getItemOffsets(
TEMP_RECT, view, mRecyclerView, mState);
result = result + TEMP_RECT.bottom - TEMP_RECT.top;
}
}
return result;
}

@Override
public int getDecorationLengthCrossAxis(View view) {
int result = 0;
if (isMainAxisDirectionHorizontal()) {
return getTopDecorationHeight(view) + getBottomDecorationHeight(view);
result = result + getTopDecorationHeight(view) + getBottomDecorationHeight(view);
for (int i = 0; i < mRecyclerView.getItemDecorationCount(); i++) {
mRecyclerView.getItemDecorationAt(i).getItemOffsets(
TEMP_RECT, view, mRecyclerView, mState);
result = result + TEMP_RECT.bottom - TEMP_RECT.top;
}
} else {
return getLeftDecorationWidth(view) + getRightDecorationWidth(view);
result = result + getLeftDecorationWidth(view) + getRightDecorationWidth(view);
for (int i = 0; i < mRecyclerView.getItemDecorationCount(); i++) {
mRecyclerView.getItemDecorationAt(i).getItemOffsets(
TEMP_RECT, view, mRecyclerView, mState);
result = result + TEMP_RECT.right + TEMP_RECT.left;
}
}
return result;
}

@Override
Expand Down Expand Up @@ -1902,11 +1928,13 @@ public void setRecycleChildrenOnDetach(boolean recycleChildrenOnDetach) {
public void onAttachedToWindow(RecyclerView recyclerView) {
super.onAttachedToWindow(recyclerView);
mParent = (View) recyclerView.getParent();
mRecyclerView = recyclerView;
}

@Override
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
super.onDetachedFromWindow(view, recycler);
mRecyclerView = null;
if (mRecycleChildrenOnDetach) {
if (DEBUG) {
Log.d(TAG, "onDetachedFromWindow. Recycling children in the recycler");
Expand Down Expand Up @@ -2357,8 +2385,7 @@ private int computeScrollRange(RecyclerView.State state) {
}

/**
* Copied from {@link RecyclerView.LayoutManager#shouldMeasureChild
* (View,
* Copied from RecyclerView.LayoutManager#shouldMeasureChild(View,
* int, int, RecyclerView.LayoutParams)}}
*/
private boolean shouldMeasureChild(View child, int widthSpec, int heightSpec,
Expand All @@ -2371,8 +2398,7 @@ private boolean shouldMeasureChild(View child, int widthSpec, int heightSpec,

/**
* Copied from
* {@link RecyclerView.LayoutManager#isMeasurementUpToDate(int, int,
* int)}
* RecyclerView.LayoutManager#isMeasurementUpToDate(int, int, int)}
*/
private static boolean isMeasurementUpToDate(int childSize, int spec, int dimension) {
final int specMode = View.MeasureSpec.getMode(spec);
Expand Down Expand Up @@ -2477,7 +2503,6 @@ private boolean isViewVisible(View view, boolean completelyVisible) {
* @see #findFirstCompletelyVisibleItemPosition()
* @see #findLastVisibleItemPosition()
*/
@SuppressWarnings("WeakerAccess")
public int findFirstVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), false);
return child == null ? NO_POSITION : getPosition(child);
Expand All @@ -2492,7 +2517,6 @@ public int findFirstVisibleItemPosition() {
* @see #findFirstVisibleItemPosition()
* @see #findLastCompletelyVisibleItemPosition()
*/
@SuppressWarnings("WeakerAccess")
public int findFirstCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), true);
return child == null ? NO_POSITION : getPosition(child);
Expand All @@ -2511,7 +2535,6 @@ public int findFirstCompletelyVisibleItemPosition() {
* @see #findLastCompletelyVisibleItemPosition()
* @see #findFirstVisibleItemPosition()
*/
@SuppressWarnings("WeakerAccess")
public int findLastVisibleItemPosition() {
final View child = findOneVisibleChild(getChildCount() - 1, -1, false);
return child == null ? NO_POSITION : getPosition(child);
Expand All @@ -2526,7 +2549,6 @@ public int findLastVisibleItemPosition() {
* @see #findLastVisibleItemPosition()
* @see #findFirstCompletelyVisibleItemPosition()
*/
@SuppressWarnings("WeakerAccess")
public int findLastCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(getChildCount() - 1, -1, true);
return child == null ? NO_POSITION : getPosition(child);
Expand Down