【问题标题】:Fill up the empty space of a FlowLayout on Android填充 Android 上 FlowLayout 的空白空间
【发布时间】:2012-12-26 21:38:57
【问题描述】:

我正在创建一个具有流式布局的应用程序。我从网上找到的FlowLayout 实现(我不记得确切来自哪里)。现在,当我的布局宽度大于其子项宽度的总和时,我需要填充空白空间,给每个适当的宽度。我试图给他们MATCH_PARENT 作为宽度,但它没有用,每个元素都是从“新行”创建的。
请帮我解决我的问题。提前致谢。

这是我使用的 FlowLayout 类实现:

public class FlowLayout extends ViewGroup {
public static final String TAG = FlowLayout.class.getSimpleName();

private int mHorizontalSpacing = 10;
private int mVerticalSpacing = 10;

public FlowLayout(Context context) {
    super(context);
}

public FlowLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
    try {
        mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);
        mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);
    } finally {
        a.recycle();
    }
}

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);

    int width = 0;
    int height = getPaddingTop();

    int currentWidth = getPaddingLeft();
    int currentHeight = 0;

    boolean breakLine = false;

    final int count = getChildCount();

    Log.d(TAG, "child count = " + count);

    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        measureChild(child, widthMeasureSpec, heightMeasureSpec);

        Log.d(TAG, "child " + i + " mw=" + child.getMeasuredWidth() + " mh=" + child.getMeasuredHeight());

        if (breakLine || currentWidth + child.getMeasuredWidth() > widthSize) {
            height += currentHeight + mVerticalSpacing;
            currentHeight = 0;
            if (currentWidth > width) width = currentWidth;
            currentWidth = getPaddingLeft();
        }

        int spacing = mHorizontalSpacing;
        if (lp.spacing != Integer.MAX_VALUE) {
            spacing = lp.spacing;
        }

        lp.x = currentWidth;
        lp.y = height;

        Log.d(TAG, "child " + i + " x=" + lp.x + " y=" + lp.y);

        currentWidth += child.getMeasuredWidth() + spacing;
        int childHeight = child.getMeasuredHeight();
        if (childHeight > currentHeight) currentHeight = childHeight;

        breakLine = lp.breakLine;
    }

    // after last row (patched by yuku)
    {
        height += currentHeight;
        if (currentWidth > width) width = currentWidth;
    }

    width += getPaddingRight();
    height += getPaddingBottom();

    Log.d(TAG, "onMeasure w=" + width + " h=" + height + " widthMeasureSpec=" + Integer.toHexString(widthMeasureSpec) + " heightMeasureSpec=" + Integer.toHexString(heightMeasureSpec));

    // don't resolve height (patched by yuku)
    setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec));
}

@Override protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
    }
}

@Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
    return p instanceof LayoutParams;
}

@Override public LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}

@Override public LayoutParams generateLayoutParams(AttributeSet attrs) {
    return new LayoutParams(getContext(), attrs);
}

@Override public LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
    return new LayoutParams(p.width, p.height);
}

public static class LayoutParams extends ViewGroup.LayoutParams {
    public boolean breakLine;
    public int spacing = Integer.MAX_VALUE;

    private int x;
    private int y;

    public LayoutParams(int width, int height) {
        super(width, height);
    }

    public LayoutParams(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout_LayoutParams);
        try {
            spacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_spacing, Integer.MAX_VALUE);
            breakLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_breakLine, false);
        } finally {
            a.recycle();
        }       
    }
}
}

我想实现这个效果:

而不是这个:

【问题讨论】:

  • 实际上没有人可以回答有关自定义未知 3rd 方控件的问题。但如果是内置的 LinearLayout,我建议在组中的任何元素上将宽度设置为 0,将权重设置为 1。
  • 嗯,我认为这是 Romain Guy 在视频中提出的自定义布局。 Karlen:您至少应该发布 FlowLayout 的确切代码。此外,您可能想尝试更详细地解释您想要发生的事情与实际发生的事情。
  • vortexx,感谢您的帮助,我会尽快尝试。 @dmon 我已经添加了你想要的信息。

标签: java android flowlayout fill-parent


【解决方案1】:

我想我明白了,这有点棘手,但这里或多或少是你需要做的。在您原来的 for 循环中,跟踪您是否已经换行。假设您将此变量称为 isOneLine 并将其初始化为 true,将 currentWidth 重置为 0 后立即将其设置为 false。然后,在您的 for 循环之外:

if (isOneLine) {
  //There's always N + 1 padding "spaces"
  int paddingBetween = (widthSize - currentWidth)/(count + 1); 

  for (int i = 0; i < count; i++) {
    View child = getChildAt(i);
    LayoutParams lp = (LayoutParams) child.getLayoutParams();
    measureChild(child, widthMeasureSpec, heightMeasureSpec);

    int spacing = mHorizontalSpacing;
    if (lp.spacing != Integer.MAX_VALUE) {
        spacing = lp.spacing;
    }
    //Not sure exactly what spacing is here, but I assume you have to take it into account somewhere...
    lp.x = paddingBetween + currentWidth;
    lp.y = 0;

    currentWidth += child.getMeasuredWidth() + spacing + paddingBetween;
  }
}

【讨论】:

  • 感谢@dmon 的回答,但我有一个问题:我找不到currentWidth 重置为0 的行。那么我必须在哪里将isOneLine 的值设置为false
  • 对,你不重置为0,重置为paddingLeft:if (breakLine || currentWidth + child.getMeasuredWidth() &gt; widthSize) {... currentWidth = getPaddingLeft(); }
  • 我已经按照你说的尝试过了,但不幸的是,它并不影响所有的流布局(我不知道为什么)。但是,有一些流程布局可以按我的意愿工作。还有其他建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多