Skip to content

Commit

Permalink
Add max line attribute to specify the maximum number of flex lines. (#…
Browse files Browse the repository at this point in the history
…424)

Add maxLine support from the XML
  • Loading branch information
thagikura authored May 16, 2018
1 parent decddb9 commit bf320b4
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.google.android.flexbox

import android.view.View
import android.view.ViewGroup
import com.google.android.flexbox.FlexContainer.NOT_SET

/**
* Fake implementation of [FlexContainer].
Expand All @@ -43,6 +44,8 @@ internal class FakeFlexContainer : FlexContainer {
@AlignContent
private var alignContent = AlignContent.STRETCH

private var maxLine = -1

override fun getFlexItemCount() = views.size

override fun getFlexItemAt(index: Int) = views[index]
Expand Down Expand Up @@ -95,6 +98,12 @@ internal class FakeFlexContainer : FlexContainer {
this.alignItems = alignItems
}

override fun getMaxLine(): Int = this.maxLine

override fun setMaxLine(maxLine: Int) {
this.maxLine = maxLine
}

override fun getFlexLines() = flexLines

override fun isMainAxisDirectionHorizontal(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3967,6 +3967,28 @@ class FlexboxAndroidTest {
assertThat(view2.right, `is`(240))
}

@Test
@FlakyTest
@Throws(Throwable::class)
fun testMaxLines() {
val activity = activityRule.activity
val flexboxLayout = createFlexboxLayout(R.layout.activity_empty_children,
object : Configuration {
override fun apply(flexboxLayout: FlexboxLayout) {
flexboxLayout.maxLine = 3
for (i in 1..50) {
val textView = createTextView(activity, i.toString(), 0)
val lp = FlexboxLayout.LayoutParams(100, 100)
lp.flexShrink = 0f
textView.layoutParams = lp
flexboxLayout.addView(textView)
}
}
})
assertThat(flexboxLayout.childCount, `is`(50))
assertThat(flexboxLayout.flexLines.size, `is`(3))
}

@Throws(Throwable::class)
private fun createFlexboxLayout(@LayoutRes activityLayoutResId: Int,
configuration: Configuration = Configuration.EMPTY): FlexboxLayout {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3310,6 +3310,30 @@ class FlexboxLayoutManagerTest {
assertThat(layoutManager.getChildAt(0).top, `is`(0))
}

@Test
@FlakyTest
@Throws(Throwable::class)
fun testMaxLine() {
val activity = activityRule.activity
val layoutManager = FlexboxLayoutManager(activity)
val adapter = TestAdapter()
activityRule.runOnUiThread {
activity.setContentView(R.layout.recyclerview)
val recyclerView = activity.findViewById<RecyclerView>(R.id.recyclerview)
layoutManager.flexDirection = FlexDirection.ROW
layoutManager.maxLine = 3
recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter
for (i in 1..50) {
val lp = createLayoutParams(activity, 100, 70)
lp.flexShrink = 0f
adapter.addItem(lp)
}
}
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
assertThat(layoutManager.flexLines.size, `is`(3))
}

/**
* Creates a new flex item.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/
interface FlexContainer {

int NOT_SET = -1;

/**
* @return the number of flex items contained in the flex container.
*/
Expand Down Expand Up @@ -270,6 +272,18 @@ interface FlexContainer {
*/
void setFlexLines(List<FlexLine> flexLines);

/**
* @return the current value of the maximum number of flex lines. If not set, {@link #NOT_SET}
* is returned.
*/
int getMaxLine();

/**
*
* @param maxLine the int value, which specifies the maximum number of flex lines
*/
void setMaxLine(int maxLine);

/**
* @return the list of the flex lines including dummy flex lines (flex line that doesn't have
* any flex items in it but used for the alignment along the cross axis), which aren't included
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static android.support.v7.widget.RecyclerView.NO_POSITION;

import static com.google.android.flexbox.FlexContainer.NOT_SET;
import static com.google.android.flexbox.FlexItem.FLEX_BASIS_PERCENT_DEFAULT;

import android.support.annotation.NonNull;
Expand Down Expand Up @@ -498,7 +499,7 @@ void calculateFlexLines(FlexLinesResult result, int mainMeasureSpec,
getViewMeasuredSizeMain(child, isMainHorizontal)
+ getFlexItemMarginStartMain(flexItem, isMainHorizontal) +
getFlexItemMarginEndMain(flexItem, isMainHorizontal),
flexItem, i, indexInFlexLine)) {
flexItem, i, indexInFlexLine, flexLines.size())) {
if (flexLine.getItemCountNotGone() > 0) {
addFlexLine(flexLines, flexLine, i > 0 ? i - 1 : 0, sumCrossSize);
sumCrossSize += flexLine.mCrossSize;
Expand Down Expand Up @@ -823,12 +824,15 @@ private int getFlexItemMarginEndCross(FlexItem flexItem, boolean isMainHorizonta
* @param childLength the length of a child view which is to be collected to the flex line
* @param flexItem the LayoutParams for the view being determined whether a new flex line
* is needed
* @param index the index of the view being added within the entire flex container
* @param indexInFlexLine the index of the view being added within the current flex line
* @param flexLinesSize the number of the existing flexlines size
* @return {@code true} if a wrap is required, {@code false} otherwise
* @see FlexContainer#getFlexWrap()
* @see FlexContainer#setFlexWrap(int)
*/
private boolean isWrapRequired(View view, int mode, int maxSize, int currentLength,
int childLength, FlexItem flexItem, int index, int indexInFlexLine) {
int childLength, FlexItem flexItem, int index, int indexInFlexLine, int flexLinesSize) {
if (mFlexContainer.getFlexWrap() == FlexWrap.NOWRAP) {
return false;
}
Expand All @@ -838,6 +842,12 @@ private boolean isWrapRequired(View view, int mode, int maxSize, int currentLeng
if (mode == View.MeasureSpec.UNSPECIFIED) {
return false;
}
int maxLine = mFlexContainer.getMaxLine();
// Judge the condition by adding 1 to the current flexLinesSize because the flex line
// being computed isn't added to the flexLinesSize.
if (maxLine != NOT_SET && maxLine <= flexLinesSize + 1) {
return false;
}
int decorationLength =
mFlexContainer.getDecorationLengthMainAxis(view, index, indexInFlexLine);
if (decorationLength > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
* <li>{@code dividerDrawable}</li>
* <li>{@code dividerDrawableHorizontal}</li>
* <li>{@code dividerDrawableVertical}</li>
* <li>{@code maxLine}</li>
* </ul>
* for the FlexboxLayout.
*
Expand Down Expand Up @@ -114,6 +115,11 @@ public class FlexboxLayout extends ViewGroup implements FlexContainer {
*/
private int mAlignContent;

/**
* The current value of the {@link }
*/
private int mMaxLine = NOT_SET;

/**
* The int definition to be used as the arguments for the {@link #setShowDivider(int)},
* {@link #setShowDividerHorizontal(int)} or {@link #setShowDividerVertical(int)}.
Expand Down Expand Up @@ -218,6 +224,7 @@ public FlexboxLayout(Context context, AttributeSet attrs, int defStyleAttr) {
.getInt(R.styleable.FlexboxLayout_justifyContent, JustifyContent.FLEX_START);
mAlignItems = a.getInt(R.styleable.FlexboxLayout_alignItems, AlignItems.STRETCH);
mAlignContent = a.getInt(R.styleable.FlexboxLayout_alignContent, AlignContent.STRETCH);
mMaxLine = a.getInt(R.styleable.FlexboxLayout_maxLine, NOT_SET);
Drawable drawable = a.getDrawable(R.styleable.FlexboxLayout_dividerDrawable);
if (drawable != null) {
setDividerDrawableHorizontal(drawable);
Expand Down Expand Up @@ -1205,6 +1212,19 @@ public void setAlignContent(@AlignContent int alignContent) {
}
}

@Override
public int getMaxLine() {
return mMaxLine;
}

@Override
public void setMaxLine(int maxLine) {
if (mMaxLine != maxLine) {
mMaxLine = maxLine;
requestLayout();
}
}

/**
* @return the flex lines composing this flex container. This method returns a copy of the
* original list excluding a dummy flex line (flex line that doesn't have any flex items in it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
*/
private int mAlignItems;

private int mMaxLine = NOT_SET;

/**
* True if the layout direction is right to left, false otherwise.
*/
Expand Down Expand Up @@ -353,6 +355,19 @@ public void setAlignContent(@AlignContent int alignContent) {
+ "if you need to use this attribute.");
}

@Override
public int getMaxLine() {
return mMaxLine;
}

@Override
public void setMaxLine(int maxLine) {
if (mMaxLine != maxLine) {
mMaxLine = maxLine;
requestLayout();
}
}

@Override
public List<FlexLine> getFlexLines() {
List<FlexLine> result = new ArrayList<>(mFlexLines.size());
Expand Down
7 changes: 7 additions & 0 deletions flexbox/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ limitations under the License.
<flag name="middle" value="2" />
<flag name="end" value="4" />
</attr>

<!--
The attribute that specifies the maximum number of flex lines. This attribute is
effective only when the flexWrap attribute is "wrap" or "wrap_reverse".
-->
<attr name="maxLine" format="integer" />

</declare-styleable>

<declare-styleable name="FlexboxLayout_Layout">
Expand Down

0 comments on commit bf320b4

Please sign in to comment.