andorid FlexboxLayout(瀑布流、标签)

本文探讨了如何在Android中使用FlexboxLayout实现动态标签布局,确保每行标签居中显示。通过参考多个资源,强调了FlexboxLayoutManager在RecyclerView中的应用,虽然存在一些限制,如不支持多行显示,但可以通过特定方式来修补这些问题。

android 动态布局标签每行标签居中显示

参考1 简洁

参考2 复杂强大

google FlexboxLayout

强大的FlexboxLayoutManager

FlexboxLayoutManage

1 RecyclerView配合FlexboxLayoutManager无比强大,你想要的效果都能实现
2 缺点只需显示2行剩下显示不完的不再显示,不支持
3 修补2的问题

    private final static int maxHeight = 130;
    private View view;

    public OnViewGlobalLayoutListener(View view) {
        this.view = view;
    }

    @Override
    public void onGlobalLayout() {
        if (view.getHeight() > maxHeight)
            view.getLayoutParams().height = maxHeight;
    }
add listener to RecyclerView:
view.getViewTreeObserver()
                  .addOnGlobalLayoutListener(new OnViewGlobalLayoutListener(view));

### 简洁版

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;

import com.google.android.flexbox.FlexboxLayout;

public class FlowTagLayout extends FlexboxLayout {
    /**
     * Should be used by subclasses to listen to changes in the dataset
     */
    AdapterDataSetObserver mDataSetObserver;

    /**
     * The adapter containing the data to be displayed by this view
     */
    ListAdapter mAdapter;

    /**
     * the tag click event callback
     */
    OnTagClickListener mOnTagClickListener;

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

    public FlowTagLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FlowTagLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

//    @Override
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//
//        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
//        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
//        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
//        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
//
//        //FlowLayout finally width and height
//        int resultWidth = 0;
//        int resultHeight = 0;
//
//        int lineWidth = 0;
//        int lineHeight = 0;
//
//        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
//            View childView = getChildAt(i);
//
//            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
//
//            int childWidth = childView.getMeasuredWidth();
//            int childHeight = childView.getMeasuredHeight();
//
//            MarginLayoutParams mlp = (MarginLayoutParams) childView.getLayoutParams();
//            int realChildWidth = childWidth + mlp.leftMargin + mlp.rightMargin;
//            int realChildHeight = childHeight + mlp.topMargin + mlp.bottomMargin;
//
//            if ((lineWidth + realChildWidth) > sizeWidth) {
//                //line feed
//                resultWidth = Math.max(lineWidth, realChildWidth);
//                resultHeight += realChildHeight;
//                //after line feed,reset lineWidth and lineHeight
//                lineWidth = realChildWidth;
//                lineHeight = realChildHeight;
//            } else {
//                lineWidth += realChildWidth;
//                lineHeight = Math.max(lineHeight, realChildHeight);
//            }
//
//            //遍历到最后一个的时候,肯定走的是不换行
//            if (i == childCount - 1) {
//                resultWidth = Math.max(lineWidth, resultWidth);
//                resultHeight += lineHeight;
//            }
//
//            setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : resultWidth,
//                    modeHeight == MeasureSpec.EXACTLY ? sizeHeight : resultHeight);
//
//        }
//
//    }
//
//    @Override
//    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//
//        int flowWidth = getWidth();
//
//        int childLeft = 0;
//        int childTop = 0;
//
//        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
//            View childView = getChildAt(i);
//
//            //skip child view  which set property to equal View.GONE
//            if (childView.getVisibility() == View.GONE) {
//                continue;
//            }
//
//            int childWidth = childView.getMeasuredWidth();
//            int childHeight = childView.getMeasuredHeight();
//
//            //child view maybe have margin
//            MarginLayoutParams mlp = (MarginLayoutParams) childView.getLayoutParams();
//
//            if (childLeft + mlp.leftMargin + childWidth + mlp.rightMargin > flowWidth) {
//                //line feed
//                childTop += (mlp.topMargin + childHeight + mlp.bottomMargin);
//                childLeft = 0;
//            }
//            //layout
//            int left = childLeft + mlp.leftMargin;
//            int top = childTop + mlp.topMargin;
//            int right = childLeft + mlp.leftMargin + childWidth;
//            int bottom = childTop + mlp.topMargin + childHeight;
//            childView.layout(left, top, right, bottom);
//
//            childLeft += (mlp.leftMargin + childWidth + mlp.rightMargin);
//        }
//    }
//
//    @Override
//    public LayoutParams generateLayoutParams(AttributeSet attrs) {
//        return new MarginLayoutParams(getContext(), attrs);
//    }

    public ListAdapter getAdapter() {
        return mAdapter;
    }

    class AdapterDataSetObserver extends DataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            reloadData();
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
        }
    }

    private void reloadData() {
        removeAllViews();
        for (int i = 0; i < mAdapter.getCount(); i++) {
            final int j = i;
            final View childView = mAdapter.getView(i, null, this);
            addView(childView, new MarginLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)));

            childView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnTagClickListener != null) {
                        mOnTagClickListener.onItemClick(FlowTagLayout.this, childView, j);
                    }
                }
            });
        }
    }


    public void setOnTagClickListener(OnTagClickListener onTagClickListener) {
        this.mOnTagClickListener = onTagClickListener;
    }

    /**
     * like ListView、GridView use FlowLayout
     *
     * @param adapter
     */
    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }

        removeAllViews();
        mAdapter = adapter;

        if (mAdapter != null) {
            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);
        }
    }

    public interface OnTagClickListener {
        void onItemClick(FlowTagLayout parent, View view, int position);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值