天天看点

仿写listview布局

package com.sfexpress.base.widget.inherit;

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class FlowLabelView extends ViewGroup {

    private int mLineSpacing;

    private int mTagSpacing;

    private boolean isReversal;
    private BaseAdapter mAdapter;

    private DataChangeObserver mObserve;
    private OnTagClickListener listener;
    private OnTagLongClickListener longClickListener;
    private boolean isUnfoldAll = true;  //是否展开全部标签

    public boolean isUnfoldAll() {
        return isUnfoldAll;
    }

    public void setUnfoldAll(boolean unfoldAll) {
        isUnfoldAll = unfoldAll;
    }

    public interface OnTagClickListener {
        void onItemClick(int position);
    }

    public interface OnTagLongClickListener {
        //消费事件返回true,否则false
        boolean onItemLongClick(int position);
    }

    public FlowLabelView(Context context) {
        super(context);
        init(context, null, 0);
    }

    public FlowLabelView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

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

    private void init(Context context, AttributeSet attributeSet, int defStyle) {
        FlowTagConfig config = new FlowTagConfig(context, attributeSet);
        mLineSpacing = config.getLineSpacing();
        mTagSpacing = config.getTagSpacing();
        isReversal = config.isReversal();
    }

    public void drawLayout() {
        if (mAdapter == null) {
            return;
        }
        this.removeAllViews();
        for (int i = 0; i < mAdapter.getCount(); i++) {
            View view = mAdapter.getView(i, null, null);
            final int position = i;
            view.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (listener != null) {
                        listener.onItemClick(position);
                    }
                }
            });
            view.setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    return longClickListener != null && longClickListener.onItemLongClick(position);
                }
            });
            this.addView(view);
        }
    }

    public void setOnTagItemClickListener(OnTagClickListener listener) {
        this.listener = listener;
    }

    public void setOnTagItemLongClickListener(OnTagLongClickListener longClickListener) {
        this.longClickListener = longClickListener;
    }

    public void setAdapter(BaseAdapter adapter) {
        if (mAdapter == null) {
            mAdapter = adapter;
            if (mObserve == null) {
                mObserve = new DataChangeObserver();
                mAdapter.registerDataSetObserver(mObserve);
            }
            drawLayout();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int needHeight = 0;   //需要的高度
        int needWidth = resolveSize(0, widthMeasureSpec);  //需要的宽度
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();

        int childLeft = paddingLeft;   //子元素离左边框的距离
        int childTop = paddingTop;   //子元素离上边框的距离

        int lineHeight = 0;   //一行需要的高度

        for (int i = 0; i < getChildCount(); i++) {
            final View childView = getChildAt(i);
            LayoutParams params = childView.getLayoutParams();
            childView.measure(getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, params.width),
                    getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, params.height));
            int childHeight = childView.getMeasuredHeight();
            int childWidth = childView.getMeasuredWidth();
            lineHeight = Math.max(childHeight, lineHeight);
            if (childLeft + childWidth + paddingRight > needWidth) {
                if (!isUnfoldAll) {
                    break;
                }
                childLeft = paddingLeft;
                lineHeight += mLineSpacing + childHeight;
            }
            childLeft += childWidth + mTagSpacing;
        }
        needHeight += childTop + lineHeight + paddingBottom;
        setMeasuredDimension(needWidth, resolveSize(needHeight, heightMeasureSpec));

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int width = r - l;
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();
        //子view横向的开始
        int childHStart = isReversal ? width - paddingRight : paddingLeft;
        int childTop = paddingTop;
        int lineHeight = 0;

        for (int i = 0; i < getChildCount(); i++) {
            final View childView = getChildAt(i);
            if (childView.getVisibility() == View.GONE) {
                continue;
            }
            int childWidth = childView.getMeasuredWidth();
            int childHeight = childView.getMeasuredHeight();
            lineHeight = Math.max(childHeight, lineHeight);

            if (isReversal) {
                if (childHStart - childWidth - paddingLeft < 0) {
                    childHStart = width - paddingRight;
                    childTop += mLineSpacing + lineHeight;
                    lineHeight = childHeight;
                }
                childView.layout(childHStart - childWidth, childTop, childHStart, childTop + childHeight);
                childHStart -= childWidth + mTagSpacing;
            } else {
                if (childHStart + childWidth + paddingRight > width) {
                    childHStart = paddingLeft;
                    childTop += mLineSpacing + lineHeight;
                    lineHeight = childHeight;
                }

                childView.layout(childHStart, childTop, childHStart + childWidth, childTop + childHeight);
                childHStart += childWidth + mTagSpacing;
            }
        }
    }

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

    class DataChangeObserver extends DataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            FlowLabelView.this.drawLayout();
        }

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


}