Skip to content

Commit d6c186b

Browse files
authored
Reduce the number of measure calls for children of Flexbox (#514)
This PR reduces the number of measure calls for the children of the Flexbox. If any items in a FlexLine don't have the flexGrow or flexShrink attributes set, the children in the FlexLine don't have to be measured in the FlexboxHelper#determineMainSize method. Similarly, if the AlignItems attribute for the Flexbox is not equal to AlignItems.STRETCH nor any items in a FlexLine don't have the AlignSelf.STRETCH attributes, the items in the FlexLine don't have to be measured in the FlexboxHelpers#stretchViews method. Also this PR changes the default values of FlexboxLayout as follows: - mAlignItems: STRETCH -> FLEX_START - mAlignContent: STRETCH -> FLEX_START
1 parent 441e885 commit d6c186b

File tree

7 files changed

+73
-10
lines changed

7 files changed

+73
-10
lines changed

flexbox/src/androidTest/java/com/google/android/flexbox/FlexboxHelperTest.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,4 +427,43 @@ class FlexboxHelperTest {
427427
assertThat(flexboxHelper.extractHigherInt(combined), `is`(higher))
428428
assertThat(flexboxHelper.extractLowerInt(combined), `is`(lower))
429429
}
430+
431+
@Test
432+
fun testFlexLine_anyItemsHaveFlexGrow() {
433+
val activity = activityRule.activity
434+
val lp1 = FlexboxLayout.LayoutParams(100, 100).apply {
435+
flexGrow = 1.0f
436+
}
437+
val view1 = View(activity)
438+
view1.layoutParams = lp1
439+
val lp2 = FlexboxLayout.LayoutParams(100, 200)
440+
val view2 = View(activity)
441+
view2.layoutParams = lp2
442+
val lp3 = FlexboxLayout.LayoutParams(100, 300)
443+
val view3 = View(activity)
444+
view3.layoutParams = lp3
445+
val lp4 = FlexboxLayout.LayoutParams(100, 400).apply {
446+
flexGrow = 2.0f
447+
}
448+
val view4 = View(activity)
449+
view4.layoutParams = lp4
450+
flexContainer.apply {
451+
addView(view1)
452+
addView(view2)
453+
addView(view3)
454+
addView(view4)
455+
flexDirection = FlexDirection.COLUMN
456+
flexWrap = FlexWrap.WRAP
457+
alignContent = AlignContent.STRETCH
458+
}
459+
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
460+
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.EXACTLY)
461+
val result = FlexboxHelper.FlexLinesResult()
462+
flexboxHelper.calculateVerticalFlexLines(result, widthMeasureSpec, heightMeasureSpec)
463+
flexContainer.flexLines = result.mFlexLines
464+
assertThat(flexContainer.flexLines.size, `is`(3))
465+
assertThat(flexContainer.flexLines[0].mAnyItemsHaveFlexGrow, `is`(true))
466+
assertThat(flexContainer.flexLines[1].mAnyItemsHaveFlexGrow, `is`(false))
467+
assertThat(flexContainer.flexLines[2].mAnyItemsHaveFlexGrow, `is`(true))
468+
}
430469
}

flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxAndroidTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,7 @@ class FlexboxAndroidTest {
833833
override fun apply(flexboxLayout: FlexboxLayout) {
834834
flexboxLayout.justifyContent = JustifyContent.FLEX_END
835835
flexboxLayout.flexDirection = FlexDirection.COLUMN
836+
flexboxLayout.alignItems = AlignItems.STRETCH
836837
}
837838
})
838839

flexbox/src/androidTest/res/layout/activity_stretch_test.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
android:layout_height="360dp"
2121
app:flexDirection="row"
2222
app:flexWrap="wrap"
23-
app:alignItems="stretch">
23+
app:alignItems="stretch"
24+
app:alignContent="stretch" >
2425

2526
<TextView
2627
android:id="@+id/text1"

flexbox/src/main/java/com/google/android/flexbox/FlexItem.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ interface FlexItem extends Parcelable {
3535
/** The default value for the flex shrink attribute */
3636
float FLEX_SHRINK_DEFAULT = 1f;
3737

38+
/** The value representing the flex shrink attribute is not set */
39+
float FLEX_SHRINK_NOT_SET = 0f;
40+
3841
/** The default value for the flex basis percent attribute */
3942
float FLEX_BASIS_PERCENT_DEFAULT = -1f;
4043

flexbox/src/main/java/com/google/android/flexbox/FlexLine.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public class FlexLine {
6565

6666
/**
6767
* The largest value of the individual child's baseline (obtained by View#getBaseline()
68-
* if the {@link FlexboxLayout#mAlignItems} value is not {@link AlignItems#BASELINE}
68+
* if the {@link FlexContainer#getAlignItems()} value is not {@link AlignItems#BASELINE}
6969
* or the flex direction is vertical, this value is not used.
7070
* If the alignment direction is from the bottom to top,
7171
* (e.g. flexWrap == WRAP_REVERSE and flexDirection == ROW)
@@ -90,6 +90,18 @@ public class FlexLine {
9090

9191
int mLastIndex;
9292

93+
/**
94+
* Set to true if any {@link FlexItem}s in this line have {@link FlexItem#getFlexGrow()}
95+
* attributes set (have the value other than {@link FlexItem#FLEX_GROW_DEFAULT})
96+
*/
97+
boolean mAnyItemsHaveFlexGrow;
98+
99+
/**
100+
* Set to true if any {@link FlexItem}s in this line have {@link FlexItem#getFlexShrink()}
101+
* attributes set (have the value other than {@link FlexItem#FLEX_SHRINK_NOT_SET})
102+
*/
103+
boolean mAnyItemsHaveFlexShrink;
104+
93105
/**
94106
* @return the size of the flex line in pixels along the main axis of the flex container.
95107
*/

flexbox/src/main/java/com/google/android/flexbox/FlexboxHelper.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import static com.google.android.flexbox.FlexContainer.NOT_SET;
2020
import static com.google.android.flexbox.FlexItem.FLEX_BASIS_PERCENT_DEFAULT;
21+
import static com.google.android.flexbox.FlexItem.FLEX_GROW_DEFAULT;
22+
import static com.google.android.flexbox.FlexItem.FLEX_SHRINK_DEFAULT;
23+
import static com.google.android.flexbox.FlexItem.FLEX_SHRINK_NOT_SET;
2124

2225
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
2326

@@ -554,6 +557,9 @@ void calculateFlexLines(FlexLinesResult result, int mainMeasureSpec,
554557
flexLine.mItemCount++;
555558
indexInFlexLine++;
556559
}
560+
flexLine.mAnyItemsHaveFlexGrow |= flexItem.getFlexGrow() != FLEX_GROW_DEFAULT;
561+
flexLine.mAnyItemsHaveFlexShrink |= flexItem.getFlexShrink() != FLEX_SHRINK_NOT_SET;
562+
557563
if (mIndexToFlexLine != null) {
558564
mIndexToFlexLine[i] = flexLines.size();
559565
}
@@ -971,10 +977,10 @@ void determineMainSize(int widthMeasureSpec, int heightMeasureSpec, int fromInde
971977
List<FlexLine> flexLines = mFlexContainer.getFlexLinesInternal();
972978
for (int i = flexLineIndex, size = flexLines.size(); i < size; i++) {
973979
FlexLine flexLine = flexLines.get(i);
974-
if (flexLine.mMainSize < mainSize) {
980+
if (flexLine.mMainSize < mainSize && flexLine.mAnyItemsHaveFlexGrow) {
975981
expandFlexItems(widthMeasureSpec, heightMeasureSpec, flexLine,
976982
mainSize, paddingAlongMainAxis, false);
977-
} else {
983+
} else if (flexLine.mMainSize > mainSize && flexLine.mAnyItemsHaveFlexShrink) {
978984
shrinkFlexItems(widthMeasureSpec, heightMeasureSpec, flexLine,
979985
mainSize, paddingAlongMainAxis, false);
980986
}
@@ -1571,15 +1577,15 @@ void stretchViews() {
15711577

15721578
/**
15731579
* Expand the view if the {@link FlexContainer#getAlignItems()} attribute is set to {@link
1574-
* AlignItems#STRETCH} or {@link FlexboxLayout.LayoutParams#mAlignSelf} is set as
1580+
* AlignItems#STRETCH} or {@link FlexItem#getAlignSelf()} is set as
15751581
* {@link AlignItems#STRETCH}.
15761582
*
15771583
* @param fromIndex the index from which value, stretch is calculated
15781584
* @see FlexContainer#getFlexDirection()
15791585
* @see FlexContainer#setFlexDirection(int)
15801586
* @see FlexContainer#getAlignItems()
15811587
* @see FlexContainer#setAlignItems(int)
1582-
* @see FlexboxLayout.LayoutParams#mAlignSelf
1588+
* @see FlexItem#getAlignSelf()
15831589
*/
15841590
void stretchViews(int fromIndex) {
15851591
if (fromIndex >= mFlexContainer.getFlexItemCount()) {
@@ -2008,6 +2014,7 @@ public int compareTo(@NonNull Order another) {
20082014
return index - another.index;
20092015
}
20102016

2017+
@NonNull
20112018
@Override
20122019
public String toString() {
20132020
return "Order{" +

flexbox/src/main/java/com/google/android/flexbox/FlexboxLayout.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,15 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer {
102102

103103
/**
104104
* The current value of the {@link AlignItems}, the default value is
105-
* {@link AlignItems#STRETCH}.
105+
* {@link AlignItems#FLEX_START}.
106106
*
107107
* @see AlignItems
108108
*/
109109
private int mAlignItems;
110110

111111
/**
112112
* The current value of the {@link AlignContent}, the default value is
113-
* {@link AlignContent#STRETCH}.
113+
* {@link AlignContent#FLEX_START}.
114114
*
115115
* @see AlignContent
116116
*/
@@ -223,8 +223,8 @@ public FlexboxLayout(Context context, AttributeSet attrs, int defStyleAttr) {
223223
mFlexWrap = a.getInt(R.styleable.FlexboxLayout_flexWrap, FlexWrap.NOWRAP);
224224
mJustifyContent = a
225225
.getInt(R.styleable.FlexboxLayout_justifyContent, JustifyContent.FLEX_START);
226-
mAlignItems = a.getInt(R.styleable.FlexboxLayout_alignItems, AlignItems.STRETCH);
227-
mAlignContent = a.getInt(R.styleable.FlexboxLayout_alignContent, AlignContent.STRETCH);
226+
mAlignItems = a.getInt(R.styleable.FlexboxLayout_alignItems, AlignItems.FLEX_START);
227+
mAlignContent = a.getInt(R.styleable.FlexboxLayout_alignContent, AlignContent.FLEX_START);
228228
mMaxLine = a.getInt(R.styleable.FlexboxLayout_maxLine, NOT_SET);
229229
Drawable drawable = a.getDrawable(R.styleable.FlexboxLayout_dividerDrawable);
230230
if (drawable != null) {

0 commit comments

Comments
 (0)