提交 163d5714 编写于 作者: T Takeshi Hagikura

Merge pull request #51 from google/evant-pull34-min

Implement the attributes for minWidth and minHeight
......@@ -64,6 +64,12 @@ public class FlexItem implements Parcelable {
public float flexBasisPercent;
/** Minimum with in DP */
public int minWidth;
/** Minimum height in DP */
public int minHeight;
public FlexItem() {
}
......@@ -90,6 +96,8 @@ public class FlexItem implements Parcelable {
dest.writeFloat(this.flexShrink);
dest.writeInt(this.alignSelf);
dest.writeFloat(this.flexBasisPercent);
dest.writeInt(this.minWidth);
dest.writeInt(this.minHeight);
}
protected FlexItem(Parcel in) {
......@@ -109,6 +117,8 @@ public class FlexItem implements Parcelable {
this.flexShrink = in.readFloat();
this.alignSelf = in.readInt();
this.flexBasisPercent = in.readFloat();
this.minWidth = in.readInt();
this.minHeight = in.readInt();
}
public FlexboxLayout.LayoutParams toLayoutParams(Context context) {
......@@ -124,6 +134,8 @@ public class FlexItem implements Parcelable {
MarginLayoutParamsCompat.setMarginStart(lp, startMargin);
MarginLayoutParamsCompat.setMarginEnd(lp, endMargin);
lp.bottomMargin = bottomMargin;
lp.minWidth = Util.dpToPixel(context, minWidth);
lp.minHeight = Util.dpToPixel(context, minHeight);
return lp;
}
......@@ -146,6 +158,8 @@ public class FlexItem implements Parcelable {
flexItem.paddingStart = ViewCompat.getPaddingStart(view);
flexItem.paddingEnd = ViewCompat.getPaddingEnd(view);
flexItem.paddingBottom = view.getPaddingBottom();
flexItem.minWidth = Util.pixelToDp(view.getContext(), lp.minWidth);
flexItem.minHeight = Util.pixelToDp(view.getContext(), lp.minHeight);
return flexItem;
}
......
......@@ -16,6 +16,7 @@
package com.google.android.apps.flexbox;
import com.google.android.apps.flexbox.validators.FixedDimensionInputValidator;
import com.google.android.apps.flexbox.validators.FlexBasisPercentInputValidator;
import com.google.android.apps.flexbox.validators.InputValidator;
import com.google.android.apps.flexbox.validators.IntegerInputValidator;
......@@ -156,6 +157,23 @@ public class FlexItemEditFragment extends DialogFragment {
new FlexEditTextWatcher(heightInput, new DimensionInputValidator(),
R.string.must_be_minus_one_or_minus_two_or_non_negative_integer));
final TextInputLayout minWidthInput = (TextInputLayout) view
.findViewById(R.id.input_layout_min_width);
EditText minWidthEdit = (EditText) view.findViewById(R.id.edit_text_min_width);
minWidthEdit.setText(String.valueOf(mFlexItem.minWidth));
minWidthEdit.addTextChangedListener(
new FlexEditTextWatcher(minWidthInput, new FixedDimensionInputValidator(),
R.string.must_be_non_negative_integer));
final TextInputLayout minHeightInput = (TextInputLayout) view
.findViewById(R.id.input_layout_min_height);
EditText minHeightEdit = (EditText) view.findViewById(
R.id.edit_text_min_height);
minHeightEdit.setText(String.valueOf(mFlexItem.minHeight));
minHeightEdit.addTextChangedListener(
new FlexEditTextWatcher(minHeightInput, new FixedDimensionInputValidator(),
R.string.must_be_non_negative_integer));
Spinner alignSelfSpinner = (Spinner) view.findViewById(
R.id.spinner_align_self);
ArrayAdapter<CharSequence> arrayAdapter = ArrayAdapter.createFromResource(getActivity(),
......@@ -200,7 +218,8 @@ public class FlexItemEditFragment extends DialogFragment {
public void onClick(View v) {
if (orderTextInput.isErrorEnabled() || flexGrowInput.isErrorEnabled() ||
flexBasisPercentInput.isErrorEnabled() || widthInput.isErrorEnabled() ||
heightInput.isErrorEnabled()) {
heightInput.isErrorEnabled() || minWidthInput.isErrorEnabled() ||
minHeightInput.isErrorEnabled()) {
Toast.makeText(getActivity(), R.string.invalid_values_exist, Toast.LENGTH_SHORT)
.show();
return;
......@@ -305,6 +324,12 @@ public class FlexItemEditFragment extends DialogFragment {
= FlexboxLayout.LayoutParams.FLEX_BASIS_PERCENT_DEFAULT;
}
break;
case R.id.input_layout_min_width:
mFlexItem.minWidth = intValue;
break;
case R.id.input_layout_min_height:
mFlexItem.minHeight = intValue;
break;
}
}
}
......
......@@ -19,7 +19,7 @@ package com.google.android.apps.flexbox.validators;
import android.text.TextUtils;
/**
* Validator for dimension values.
* Validator for dimension values including match_parent and wrap_content.
*/
public class DimensionInputValidator implements InputValidator {
......
/*
* 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.
*/
package com.google.android.apps.flexbox.validators;
import android.text.TextUtils;
/**
* Validator for dimension values.
*/
public class FixedDimensionInputValidator implements InputValidator {
@Override
public boolean isValidInput(CharSequence charSequence) {
return !TextUtils.isEmpty(charSequence) && TextUtils.isDigitsOnly(charSequence);
}
}
......@@ -114,6 +114,36 @@ limitations under the License.
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/input_layout_min_width"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/edit_text_min_width"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:singleLine="true"
android:inputType="number"
android:hint="@string/hint_min_width" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/input_layout_min_height"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/edit_text_min_height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:singleLine="true"
android:inputType="number"
android:hint="@string/hint_min_height" />
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
......
......@@ -100,8 +100,11 @@ limitations under the License.
<string name="hint_align_self">Align Self</string>
<string name="hint_width">Width (-1: match_parent, -2: wrap_content)</string>
<string name="hint_height">Height (-1: match_parent, -2: wrap_content)</string>
<string name="hint_min_width">Min Width</string>
<string name="hint_min_height">Min Height</string>
<string name="must_be_non_negative_float">Must be a non-negative float value</string>
<string name="must_be_non_negative_integer">Must be a non-negative integer value</string>
<string name="must_be_minus_one_or_minus_two_or_non_negative_integer">Must be -1 or -2 or a non-negative integer value</string>
<string name="must_be_integer">Must be an integer value</string>
<string name="must_be_minus_one_or_non_negative_integer">Must be -1 or a non-negative integer value</string>
......
......@@ -19,12 +19,16 @@ package com.google.android.flexbox.test;
import com.google.android.flexbox.FlexboxLayout;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.ViewAssertion;
import android.support.test.espresso.assertion.ViewAssertions;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
......@@ -43,6 +47,7 @@ import static android.support.test.espresso.assertion.PositionAssertions.isRight
import static android.support.test.espresso.assertion.PositionAssertions.isRightOf;
import static android.support.test.espresso.assertion.PositionAssertions.isTopAlignedWith;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
......@@ -694,7 +699,8 @@ public class FlexboxAndroidTest {
// Both the parent FrameLayout and the FlexboxLayout have different padding values
// but the text3.getRight should be the padding value for the FlexboxLayout, not including
// the parent's padding value
assertThat(flexboxLayout.getWidth() - text3.getRight(), is(flexboxLayout.getPaddingRight()));
assertThat(flexboxLayout.getWidth() - text3.getRight(),
is(flexboxLayout.getPaddingRight()));
assertThat(text3.getTop(), is(flexboxLayout.getPaddingTop()));
}
......@@ -2446,6 +2452,104 @@ public class FlexboxAndroidTest {
totalHeight <= flexboxLayout.getHeight() + 3);
}
@Test
@FlakyTest(tolerance = TOLERANCE)
public void testMinWidth_initial_width_less_than_minWidth() throws Throwable {
final FlexboxTestActivity activity = mActivityRule.getActivity();
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.setContentView(R.layout.activity_minwidth_test);
}
});
// This test case verifies if the minWidth attribute works as a minimum constraint
// If the initial view width is less than the value of minWidth.
// The textView1's layout_width is set to wrap_content and its text is "1" apparently
// the initial measured width is less than the value of layout_minWidth (100dp)
FlexboxLayout flexboxLayout = (FlexboxLayout) activity.findViewById(R.id.flexbox_layout);
TextView textView1 = (TextView) activity.findViewById(R.id.text1);
int minWidth = ((FlexboxLayout.LayoutParams) textView1.getLayoutParams()).minWidth;
onView(withId(R.id.text1)).check(hasWidth(minWidth));
onView(withId(R.id.text2)).check(hasWidth(flexboxLayout.getWidth() - minWidth));
}
@Test
@FlakyTest(tolerance = TOLERANCE)
public void testMinWidth_works_as_lower_bound_shrink_to() throws Throwable {
final FlexboxTestActivity activity = mActivityRule.getActivity();
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.setContentView(R.layout.activity_minwidth_lower_bound_test);
}
});
// This test case verifies if the minWidth attribute works as a lower bound
// when the view would shrink less than the minWidth if the minWidth weren't set
FlexboxLayout flexboxLayout = (FlexboxLayout) activity.findViewById(R.id.flexbox_layout);
TextView textView1 = (TextView) activity.findViewById(R.id.text1);
TextView textView2 = (TextView) activity.findViewById(R.id.text2);
TextView textView3 = (TextView) activity.findViewById(R.id.text3);
TextView textView4 = (TextView) activity.findViewById(R.id.text4);
int minWidth = ((FlexboxLayout.LayoutParams) textView1.getLayoutParams()).minWidth;
onView(withId(R.id.text1)).check(hasWidth(minWidth));
assertEquals(flexboxLayout.getWidth(),
textView1.getWidth() + textView2.getWidth() + textView3.getWidth() + textView4
.getWidth());
}
@Test
@FlakyTest(tolerance = TOLERANCE)
public void testMinHeight_initial_height_less_than_minHeight() throws Throwable {
final FlexboxTestActivity activity = mActivityRule.getActivity();
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.setContentView(R.layout.activity_minheight_test);
}
});
// This test case verifies if the minHeight attribute works as a minimum constraint
// If the initial view height is less than the value of minHeight.
// The textView1's layout_height is set to wrap_content and its text is "1" apparently
// the initial measured height is less than the value of layout_minHeight (100dp)
FlexboxLayout flexboxLayout = (FlexboxLayout) activity.findViewById(R.id.flexbox_layout);
TextView textView1 = (TextView) activity.findViewById(R.id.text1);
int minHeight = ((FlexboxLayout.LayoutParams) textView1.getLayoutParams()).minHeight;
onView(withId(R.id.text1)).check(hasHeight(minHeight));
onView(withId(R.id.text2)).check(hasHeight(flexboxLayout.getHeight() - minHeight));
}
@Test
@FlakyTest(tolerance = TOLERANCE)
public void testMinHeight_works_as_lower_bound_shrink_to() throws Throwable {
final FlexboxTestActivity activity = mActivityRule.getActivity();
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.setContentView(R.layout.activity_minheight_lower_bound_test);
}
});
// This test case verifies if the minHeight attribute works as a lower bound
// when the view would shrink less than the minHeight if the minHeight weren't set
FlexboxLayout flexboxLayout = (FlexboxLayout) activity.findViewById(R.id.flexbox_layout);
TextView textView1 = (TextView) activity.findViewById(R.id.text1);
TextView textView2 = (TextView) activity.findViewById(R.id.text2);
TextView textView3 = (TextView) activity.findViewById(R.id.text3);
TextView textView4 = (TextView) activity.findViewById(R.id.text4);
int minHeight = ((FlexboxLayout.LayoutParams) textView1.getLayoutParams()).minHeight;
onView(withId(R.id.text1)).check(hasHeight(minHeight));
assertEquals(flexboxLayout.getHeight(),
textView1.getHeight() + textView2.getHeight() + textView3.getHeight()
+ textView4.getHeight());
}
@Test
@FlakyTest(tolerance = TOLERANCE)
public void testView_visibility_gone() throws Throwable {
......@@ -2518,4 +2622,42 @@ public class FlexboxAndroidTest {
textView.setLayoutParams(lp);
return textView;
}
private ViewAssertion hasWidth(final int width) {
return ViewAssertions.matches(new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("expected width: " + width);
}
@Override
protected void describeMismatchSafely(View item, Description mismatchDescription) {
mismatchDescription.appendText("actual width: " + item.getWidth());
}
@Override
protected boolean matchesSafely(View item) {
return item.getWidth() == width;
}
});
}
private ViewAssertion hasHeight(final int height) {
return ViewAssertions.matches(new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("expected height: " + height);
}
@Override
protected void describeMismatchSafely(View item, Description mismatchDescription) {
mismatchDescription.appendText("actual height: " + item.getHeight());
}
@Override
protected boolean matchesSafely(View item) {
return item.getHeight() == height;
}
});
}
}
<?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 android:id="@+id/flexbox_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="400dp"
android:layout_height="400dp"
app:flexDirection="column"
app:flexWrap="nowrap" >
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:text="1"
app:layout_minHeight="150dp" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:text="2" />
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:text="3" />
<TextView
android:id="@+id/text4"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:text="4" />
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
<?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 android:id="@+id/flexbox_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="400dp"
android:layout_height="400dp"
app:flexDirection="column">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
app:layout_minHeight="100dp" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="2"
app:layout_flexGrow="1" />
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
<?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 android:id="@+id/flexbox_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="400dp"
android:layout_height="400dp"
app:flexWrap="nowrap" >
<TextView
android:id="@+id/text1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="1"
app:layout_minWidth="150dp" />
<TextView
android:id="@+id/text2"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="2" />
<TextView
android:id="@+id/text3"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="3" />
<TextView
android:id="@+id/text4"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="4" />
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
<?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 android:id="@+id/flexbox_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="400dp"
android:layout_height="400dp">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
app:layout_minWidth="100dp" />
<TextView
android:id="@+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="2"
app:layout_flexGrow="1" />
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
......@@ -57,6 +57,8 @@ import java.util.List;
* <li>{@code layout_flexShrink}</li>
* <li>{@code layout_flexBasisPercent}</li>
* <li>{@code layout_alignSelf}</li>
* <li>{@code layout_minWidth}</li>
* <li>{@code layout_minHeight}</li>
* </ul>
*/
public class FlexboxLayout extends ViewGroup {
......@@ -219,6 +221,13 @@ public class FlexboxLayout extends ViewGroup {
private List<FlexLine> mFlexLines = new ArrayList<>();
/**
* Holds the 'frozen' state of children during measure. If a view is frozen it will no longer
* expand or shrink regardless of flexGrow/flexShrink. Items are indexed by the child's
* reordered index.
*/
private boolean[] mChildrenFrozen;
public FlexboxLayout(Context context) {
this(context, null);
}
......@@ -247,6 +256,9 @@ public class FlexboxLayout extends ViewGroup {
if (isOrderChangedFromLastMeasurement()) {
mReorderedIndices = createReorderedIndices();
}
// TODO: Move the object allocation to other methods instead of onMeasure
mChildrenFrozen = new boolean[getChildCount()];
// TODO: Only calculate the children views which are affected from the last measure.
switch (mFlexDirection) {
......@@ -459,6 +471,16 @@ public class FlexboxLayout extends ViewGroup {
getPaddingTop() + getPaddingBottom() + lp.topMargin
+ lp.bottomMargin, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
// Check the minimum constraint after the first measurement for the child
// To prevent the child's width becomes less than the value of minWidth
// E.g. When the child's layout_width is wrap_content the measured width may be
// less than the min width after the first measurement.
if (child.getMeasuredWidth() < lp.minWidth) {
child.measure(MeasureSpec.makeMeasureSpec(lp.minWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(),
MeasureSpec.EXACTLY));
}
childState = ViewCompat
.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));
largestHeightInRow = Math.max(largestHeightInRow,
......@@ -602,6 +624,16 @@ public class FlexboxLayout extends ViewGroup {
getPaddingTop() + getPaddingBottom() + lp.topMargin
+ lp.bottomMargin, childHeight);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
// Check the minimum constraint after the first measurement for the child
// To prevent the child's height becomes less than the value of minHeight
// E.g. When the child's layout_height is wrap_content the measured height may be
// less than the min height after the first measurement.
if (child.getMeasuredHeight() < lp.minHeight) {
child.measure(
MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(lp.minHeight, MeasureSpec.EXACTLY));
}
childState = ViewCompat
.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child));
largestWidthInColumn = Math.max(largestWidthInColumn,
......@@ -817,59 +849,70 @@ public class FlexboxLayout extends ViewGroup {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (flexDirection == FLEX_DIRECTION_ROW
|| flexDirection == FLEX_DIRECTION_ROW_REVERSE) {
float rawCalculatedWidth = child.getMeasuredWidth() - unitShrink * lp.flexShrink;
if (i == flexLine.itemCount - 1) {
rawCalculatedWidth += accumulatedRoundError;
accumulatedRoundError = 0;
}
int newWidth = Math.round(rawCalculatedWidth);
if (newWidth < 0) {
// This means the child doesn't have enough space to distribute the negative
// free space. To adjust the flex line length down to the maxMainSize, remaining
// negative free space needs to be re-distributed to other flex items
// (children views). In that case, invoke this method again with the same
// startIndex.
needsReshrink = true;
newWidth = 0;
} else {
accumulatedRoundError += (rawCalculatedWidth - newWidth);
if (accumulatedRoundError > 1.0) {
newWidth += 1;
accumulatedRoundError -= 1;
} else if (accumulatedRoundError < -1.0) {
newWidth -= 1;
accumulatedRoundError += 1;
// The direction of main axis is horizontal
if (!mChildrenFrozen[childIndex]) {
float rawCalculatedWidth = child.getMeasuredWidth()
- unitShrink * lp.flexShrink;
if (i == flexLine.itemCount - 1) {
rawCalculatedWidth += accumulatedRoundError;
accumulatedRoundError = 0;
}
int newWidth = Math.round(rawCalculatedWidth);
if (newWidth < lp.minWidth) {
// This means the child doesn't have enough space to distribute the negative
// free space. To adjust the flex line length down to the maxMainSize, remaining
// negative free space needs to be re-distributed to other flex items
// (children views). In that case, invoke this method again with the same
// startIndex.
needsReshrink = true;
newWidth = lp.minWidth;
mChildrenFrozen[childIndex] = true;
flexLine.totalFlexShrink -= lp.flexShrink;
} else {
accumulatedRoundError += (rawCalculatedWidth - newWidth);
if (accumulatedRoundError > 1.0) {
newWidth += 1;
accumulatedRoundError -= 1;
} else if (accumulatedRoundError < -1.0) {
newWidth -= 1;
accumulatedRoundError += 1;
}
}
child.measure(MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(),
MeasureSpec.EXACTLY));
}
child.measure(MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY),
MeasureSpec
.makeMeasureSpec(child.getMeasuredHeight(),
MeasureSpec.EXACTLY));
flexLine.mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
} else {
float rawCalculatedHeight = child.getMeasuredHeight() - unitShrink * lp.flexShrink;
if (i == flexLine.itemCount - 1) {
rawCalculatedHeight += accumulatedRoundError;
accumulatedRoundError = 0;
}
int newHeight = Math.round(rawCalculatedHeight);
if (newHeight < 0) {
// Need to invoke this method again like the case flex direction is vertical
needsReshrink = true;
newHeight = 0;
} else {
accumulatedRoundError += (rawCalculatedHeight - newHeight);
if (accumulatedRoundError > 1.0) {
newHeight += 1;
accumulatedRoundError -= 1;
} else if (accumulatedRoundError < -1.0) {
newHeight -= 1;
accumulatedRoundError += 1;
// The direction of main axis is vertical
if (!mChildrenFrozen[childIndex]) {
float rawCalculatedHeight = child.getMeasuredHeight()
- unitShrink * lp.flexShrink;
if (i == flexLine.itemCount - 1) {
rawCalculatedHeight += accumulatedRoundError;
accumulatedRoundError = 0;
}
int newHeight = Math.round(rawCalculatedHeight);
if (newHeight < lp.minHeight) {
// Need to invoke this method again like the case flex direction is vertical
needsReshrink = true;
newHeight = lp.minHeight;
mChildrenFrozen[childIndex] = true;
flexLine.totalFlexShrink -= lp.flexShrink;
} else {
accumulatedRoundError += (rawCalculatedHeight - newHeight);
if (accumulatedRoundError > 1.0) {
newHeight += 1;
accumulatedRoundError -= 1;
} else if (accumulatedRoundError < -1.0) {
newHeight -= 1;
accumulatedRoundError += 1;
}
}
child.measure(MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
}
child.measure(MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
flexLine.mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
}
childIndex++;
......@@ -1827,6 +1870,16 @@ public class FlexboxLayout extends ViewGroup {
*/
public float flexBasisPercent = FLEX_BASIS_PERCENT_DEFAULT;
/**
* This attribute determines the minimum width the child can shrink to.
*/
public int minWidth;
/**
* This attribute determines the minimum height the child can shrink to.
*/
public int minHeight;
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
......@@ -1842,6 +1895,9 @@ public class FlexboxLayout extends ViewGroup {
flexBasisPercent = a
.getFraction(R.styleable.FlexboxLayout_Layout_layout_flexBasisPercent, 1, 1,
FLEX_BASIS_PERCENT_DEFAULT);
minWidth = a.getDimensionPixelSize(R.styleable.FlexboxLayout_Layout_layout_minWidth, 0);
minHeight = a
.getDimensionPixelSize(R.styleable.FlexboxLayout_Layout_layout_minHeight, 0);
a.recycle();
}
......
......@@ -99,5 +99,8 @@ limitations under the License.
<enum name="baseline" value="3" />
<enum name="stretch" value="4" />
</attr>
<attr name="layout_minWidth" format="dimension" />
<attr name="layout_minHeight" format="dimension" />
</declare-styleable>
</resources>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册