提交 7b1f3a50 编写于 作者: T Takeshi Hagikura

Fixes the issue #62

This fixes the edge case where the child's width is WRAP_CONTENT and some
of the contents along the main axis would be truncated if parent's padding
is added (if this is the case, remeasure the child with accumulated width
taken into account to avoid some of the contents to be truncated).
Because accumulated width is not taken into account in the first
measurement of each child (because FlexboxLayout has the concept of wrapping,
at the first measurement of each child, we want the child to be big as it
wants even if there is not enough left over space)

Change-Id: I949fe6b549b5f7c10255ad5fcf6d05fb9a58eeec
上级 5a16e8de
......@@ -2849,6 +2849,36 @@ public class FlexboxAndroidTest {
assertThat(flexboxLayout.getChildCount(), is(0));
}
@FlakyTest(tolerance = TOLERANCE)
public void testParentPadding_children_wrap_content() throws Throwable {
final FlexboxTestActivity activity = mActivityRule.getActivity();
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.setContentView(R.layout.activity_parent_padding_children_wrap_content);
}
});
FlexboxLayout flexboxLayout = (FlexboxLayout) activity.findViewById(R.id.flexbox_layout);
assertThat(flexboxLayout.getFlexWrap(), is(FlexboxLayout.FLEX_WRAP_WRAP));
assertThat(flexboxLayout.getFlexDirection(), is(FlexboxLayout.FLEX_DIRECTION_ROW));
assertThat(flexboxLayout.getAlignItems(), is(FlexboxLayout.ALIGN_ITEMS_FLEX_START));
onView(withId(R.id.text1)).check(isTopAlignedWith(withId(R.id.flexbox_layout)));
onView(withId(R.id.text1)).check(isLeftAlignedWith(withId(R.id.flexbox_layout)));
onView(withId(R.id.text2)).check(isTopAlignedWith(withId(R.id.flexbox_layout)));
onView(withId(R.id.text2)).check(isRightOf(withId(R.id.text1)));
onView(withId(R.id.text2)).check(isBottomAlignedWith(withId(R.id.flexbox_layout)));
onView(withId(R.id.text3)).check(isBelow(withId(R.id.text1)));
onView(withId(R.id.text3)).check(isBelow(withId(R.id.text2)));
onView(withId(R.id.text3)).check(isLeftAlignedWith(withId(R.id.flexbox_layout)));
TextView text1 = (TextView) activity.findViewById(R.id.text1);
TextView text2 = (TextView) activity.findViewById(R.id.text2);
// The second TextView's height should be larger than the first one because otherwise the
// text in the second one doesn't fit in the first flex line (because of parrent padding)
assertTrue(text1.getHeight() < text2.getHeight());
}
private TextView createTextView(Context context, String text, int order) {
TextView textView = new TextView(context);
textView.setText(text);
......
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2016 Google Inc. All rights reserved.
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.
-->
<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/flexbox_layout"
android:layout_width="360dp"
android:layout_height="300dp"
android:padding="16dp"
app:flexWrap="wrap"
app:alignItems="flex_start">
<TextView
android:id="@+id/text1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="1"
android:layout_margin="-16dp"
app:layout_flexBasisPercent="100%" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2222" />
<TextView
android:id="@+id/text3"
android:layout_width="160dp"
android:layout_height="120dp"
android:text="3" />
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
......@@ -447,15 +447,16 @@ public class FlexboxLayout extends ViewGroup {
int paddingEnd = ViewCompat.getPaddingEnd(this);
int largestHeightInRow = Integer.MIN_VALUE;
FlexLine flexLine = new FlexLine();
flexLine.mainSize = paddingStart;
flexLine.mainSize = 0;
int heightUsed = getPaddingTop() + getPaddingBottom();
for (int i = 0; i < childCount; i++) {
View child = getReorderedChildAt(i);
if (child == null) {
addFlexLineIfLastFlexItem(i, childCount, paddingEnd, flexLine);
addFlexLineIfLastFlexItem(i, childCount, paddingStart + paddingEnd, flexLine);
continue;
} else if (child.getVisibility() == View.GONE) {
flexLine.itemCount++;
addFlexLineIfLastFlexItem(i, childCount, paddingEnd, flexLine);
addFlexLineIfLastFlexItem(i, childCount, paddingStart + paddingEnd, flexLine);
continue;
}
......@@ -483,6 +484,23 @@ public class FlexboxLayout extends ViewGroup {
+ lp.bottomMargin, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
int totalWidthWithoutParentPadding = flexLine.mainSize + child.getMeasuredWidth();
if (lp.width == LayoutParams.WRAP_CONTENT
&& mFlexWrap != FLEX_WRAP_NOWRAP
&& totalWidthWithoutParentPadding < widthSize
&& totalWidthWithoutParentPadding + paddingEnd + paddingStart > widthSize) {
// This is for the edge case where the child's width is WRAP_CONTENT and some
// of the contents along the main axis would be truncated if parent's padding
// is added (if this is the case, remeasure the child with accumulated width
// taken into account to avoid some of the contents to be truncated).
// Because accumulated width is not taken into account in the first
// measurement of each child (because FlexboxLayout has the concept of wrapping,
// at the first measurement of each child, we want the child to be big as it
// wants even if there is not enough left over space)
measureChildWithMargins(child, widthMeasureSpec, flexLine.mainSize,
heightMeasureSpec, heightUsed);
}
// Check the size constraint after the first measurement for the child
// To prevent the child's width/height violate the size constraints imposed by the
// {@link LayoutParams#minWidth}, {@link LayoutParams#minHeight},
......@@ -495,21 +513,22 @@ public class FlexboxLayout extends ViewGroup {
.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));
largestHeightInRow = Math.max(largestHeightInRow,
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
flexLine.crossSize = Math.max(flexLine.crossSize, largestHeightInRow);
if (isWrapRequired(mFlexWrap, widthMode, widthSize, flexLine.mainSize,
child.getMeasuredWidth(), lp)) {
flexLine.mainSize += paddingEnd;
flexLine.mainSize += (paddingStart + paddingEnd);
mFlexLines.add(flexLine);
heightUsed += flexLine.crossSize;
flexLine = new FlexLine();
flexLine.itemCount = 1;
flexLine.mainSize = paddingStart;
flexLine.mainSize = 0;
largestHeightInRow = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
} else {
flexLine.itemCount++;
}
flexLine.mainSize += child.getMeasuredWidth() + lp.leftMargin
+ lp.rightMargin;
flexLine.mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
flexLine.totalFlexGrow += lp.flexGrow;
flexLine.totalFlexShrink += lp.flexShrink;
// Temporarily set the cross axis length as the largest child in the row
......@@ -529,7 +548,7 @@ public class FlexboxLayout extends ViewGroup {
child.getMeasuredHeight() - child.getBaseline()
+ lp.bottomMargin);
}
addFlexLineIfLastFlexItem(i, childCount, paddingEnd, flexLine);
addFlexLineIfLastFlexItem(i, childCount, paddingStart + paddingEnd, flexLine);
}
}
......@@ -598,15 +617,16 @@ public class FlexboxLayout extends ViewGroup {
int paddingBottom = getPaddingBottom();
int largestWidthInColumn = Integer.MIN_VALUE;
FlexLine flexLine = new FlexLine();
flexLine.mainSize = paddingTop;
flexLine.mainSize = 0;
int widthUsed = getPaddingLeft() + getPaddingLeft();
for (int i = 0; i < childCount; i++) {
View child = getReorderedChildAt(i);
if (child == null) {
addFlexLineIfLastFlexItem(i, childCount, paddingBottom, flexLine);
addFlexLineIfLastFlexItem(i, childCount, paddingTop + paddingBottom, flexLine);
continue;
} else if (child.getVisibility() == View.GONE) {
flexLine.itemCount++;
addFlexLineIfLastFlexItem(i, childCount, paddingBottom, flexLine);
addFlexLineIfLastFlexItem(i, childCount, paddingTop + paddingBottom, flexLine);
continue;
}
......@@ -634,6 +654,23 @@ public class FlexboxLayout extends ViewGroup {
+ lp.bottomMargin, childHeight);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
int totalHeightWithoutParentPadding = flexLine.mainSize + child.getMeasuredWidth();
if (lp.height == LayoutParams.WRAP_CONTENT
&& mFlexWrap != FLEX_WRAP_NOWRAP
&& totalHeightWithoutParentPadding < heightSize
&& totalHeightWithoutParentPadding + paddingTop + paddingBottom > heightSize) {
// This is for the edge case where the child's height is WRAP_CONTENT and some
// of the contents along the main axis would be truncated if parent's padding
// is added (if this is the case, remeasure the child height with accumulated height
// taken into account to avoid some of the contents to be truncated).
// Because accumulated height is not taken into account in the first
// measurement of each child (because FlexboxLayout has the concept of wrapping,
// at the first measurement of each child, we want the child to be big as it
// wants even if there is not enough left over space)
measureChildWithMargins(child, widthMeasureSpec, widthUsed,
heightMeasureSpec, flexLine.mainSize);
}
// Check the size constraint after the first measurement for the child
// To prevent the child's width/height violate the size constraints imposed by the
// {@link LayoutParams#minWidth}, {@link LayoutParams#minHeight},
......@@ -646,15 +683,17 @@ public class FlexboxLayout extends ViewGroup {
.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));
largestWidthInColumn = Math.max(largestWidthInColumn,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
flexLine.crossSize = Math.max(flexLine.crossSize, largestWidthInColumn);
if (isWrapRequired(mFlexWrap, heightMode, heightSize, flexLine.mainSize,
child.getMeasuredHeight(), lp)) {
flexLine.mainSize += paddingBottom;
flexLine.mainSize += (paddingTop + paddingBottom);
mFlexLines.add(flexLine);
widthUsed += flexLine.crossSize;
flexLine = new FlexLine();
flexLine.itemCount = 1;
flexLine.mainSize = paddingTop;
flexLine.mainSize = 0;
largestWidthInColumn = child.getMeasuredWidth() + lp.leftMargin
+ lp.rightMargin;
} else {
......@@ -668,7 +707,7 @@ public class FlexboxLayout extends ViewGroup {
// later
flexLine.crossSize = Math.max(flexLine.crossSize, largestWidthInColumn);
addFlexLineIfLastFlexItem(i, childCount, paddingBottom, flexLine);
addFlexLineIfLastFlexItem(i, childCount, paddingTop + paddingBottom, flexLine);
}
determineMainSize(mFlexDirection, widthMeasureSpec, heightMeasureSpec);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册