How can I do something like a FlowLayout in Android?

后端 未结 9 1409
情歌与酒
情歌与酒 2020-11-22 08:11

How can I do something like a FlowLayout in Android?

9条回答
  •  天涯浪人
    2020-11-22 08:41

    Like one of the previous answers, I started with the solution here: http://hzqtc.github.io/2013/12/android-custom-layout-flowlayout.html

    I extended it to account for varying heights of children as below.

    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;
    
    // Custom layout that wraps child views to a new line
    public class FlowLayout extends ViewGroup {
    
        private int marginHorizontal;
        private int marginVertical;
    
        public FlowLayout(Context context) {
            super(context);
            init();
        }
    
        public FlowLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        private void init() { // Specify the margins for the children
            marginHorizontal = getResources().getDimensionPixelSize(R.dimen.activity_half_horizontal_margin);
            marginVertical = getResources().getDimensionPixelSize(R.dimen.activity_half_vertical_margin);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int childLeft = getPaddingLeft();
            int childTop = getPaddingTop();
            int lowestBottom = 0;
            int lineHeight = 0;
            int myWidth = resolveSize(100, widthMeasureSpec);
            int wantedHeight = 0;
    
            for (int i = 0; i < getChildCount(); i++) {
                final View child = getChildAt(i);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }
    
                child.measure(getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
                        getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
                int childWidth = child.getMeasuredWidth();
                int childHeight = child.getMeasuredHeight();
                lineHeight = Math.max(childHeight, lineHeight);
    
                if (childWidth + childLeft + getPaddingRight() > myWidth) { // Wrap this line
                    childLeft = getPaddingLeft();
                    childTop = marginVertical + lowestBottom; // Spaced below the previous lowest point
                    lineHeight = childHeight;
                }
                childLeft += childWidth + marginHorizontal;
    
                if (childHeight + childTop > lowestBottom) { // New lowest point
                    lowestBottom = childHeight + childTop;
                }
            }
    
            wantedHeight += childTop + lineHeight + getPaddingBottom();
            setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            int childLeft = getPaddingLeft();
            int childTop = getPaddingTop();
            int lowestBottom = 0;
            int myWidth = right - left;
            for (int i = 0; i < getChildCount(); i++) {
                final View child = getChildAt(i);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }
                int childWidth = child.getMeasuredWidth();
                int childHeight = child.getMeasuredHeight();
    
                if (childWidth + childLeft + getPaddingRight() > myWidth) { // Wrap this line
                    childLeft = getPaddingLeft();
                    childTop = marginVertical + lowestBottom; // Spaced below the previous lowest point
                }
                child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
                childLeft += childWidth + marginHorizontal;
    
                if (childHeight + childTop > lowestBottom) { // New lowest point
                    lowestBottom = childHeight + childTop;
                }
            }
        }
    }
    

    I used this as a solution for wrapping multi-line TextEdits. Hope it helps!

提交回复
热议问题