android 一些通用view(2)

TagLayout

import android.content.Context ;
import android.content.res.TypedArray ;
import android.util.AttributeSet ;
import android.util.Log ;
import android.util.SparseArray ;
import android.view.View ;
import android.view.ViewGroup ;

import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.List ;

/**
* Created by whuthm
*/
public class TagLayout extends ViewGroup implements View.OnClickListener ,
        ViewGroup.OnHierarchyChangeListener {
   
    private int mHorizontalSpacing;
    private int mVerticalSpacing ;
    private boolean mSingleChoice ;
   
    private SparseArray<List<View>> mSparseViews = new SparseArray<List<View>>() ;
    private SparseArray<Integer> mSparseHeights = new SparseArray<Integer>();
   
    private HashMap<Object , Boolean> mTagStates = new HashMap<Object , Boolean>();
   
    private OnTagSelectedListener mTagListener;
   
    public TagLayout(Context context) {
        this (context, null) ;
    }
   
    public TagLayout(Context context, AttributeSet attrs) {
        this (context, attrs , 0) ;
    }
   
    public TagLayout(Context context, AttributeSet attrs , int defStyle) {
        super (context, attrs , defStyle);
        final TypedArray a = context.obtainStyledAttributes(attrs , R.styleable.TagLayout);
        mSingleChoice = a.getBoolean(R.styleable.TagLayout_singleChoice, true );
        mHorizontalSpacing = a.getDimensionPixelOffset(
                R.styleable.TagLayout_android_horizontalSpacing, 0 );
        mHorizontalSpacing = Math.max(0 , mHorizontalSpacing) ;
        mVerticalSpacing = a.getDimensionPixelOffset(
                R.styleable.TagLayout_android_verticalSpacing, 0 );
        mVerticalSpacing = Math.max(0 , mVerticalSpacing) ;
        a.recycle() ;
       
        setOnHierarchyChangeListener( this);
    }
   
    public void setOnTagSelectedListener(OnTagSelectedListener l) {
        mTagListener = l;
    }
   
    private void notifyTagSelectedChange(Object tag, boolean selected) {
        mTagStates .put(tag, selected) ;
        if ( mTagListener != null ) {
            mTagListener .onTagSelectedChange(tag, selected) ;
        }
    }
   
    public void addTag(Object tag, View child) {
        addTag(tag, child, false) ;
    }
   
    public void addTag(Object tag, View child, boolean selected) {
        child.setTag(tag);
        addView(child) ;
       
        setChildrenSelected(child , selected);
    }
   
    @Override
    public void addView(View child, int index, LayoutParams params) {
        Object tag = child.getTag();
        if (tag != null) {
            if (!mTagStates.containsKey(tag)) {
                super.addView(child , index, params);
                child.setOnClickListener(this );
                mTagStates.put(tag , child.isSelected());
            }
            else {
                Log.e("TagLayout" , "tag duplicate : " + tag) ;
            }
        }
        else {
            Log.e ("TagLayout" , "tag = null") ;
        }
    }
   
    private void setChildrenSelected(View curChild, boolean curSelected) {
        int curIndex = indexOfChild(curChild) ;
        if (curIndex >= 0) {
            if (mSingleChoice) {
                if (!curSelected) {
                    return;
                }
                int count = getChildCount() ;
                for (int i = 0; i < count; i++) {
                    View v = getChildAt(i) ;
                    boolean isSelected = v.isSelected();
                    if (curSelected) {
                        v.setSelected(i == curIndex) ;
                        if (isSelected != v.isSelected()) {
                            notifyTagSelectedChange(v.getTag() , v.isSelected());
                        }
                    }
                }
            }
            else {
                boolean isSelected = curChild.isSelected() ;
                if (isSelected != curSelected) {
                    curChild.setSelected(curSelected) ;
                    notifyTagSelectedChange(curChild.getTag(), curChild.isSelected()) ;
                }
            }
        }
       
    }
   
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       
        mSparseViews .clear();
        mSparseHeights .clear();
       
        measureChildren(widthMeasureSpec , heightMeasureSpec);
        final int widthSpecMode = MeasureSpec. getMode(widthMeasureSpec) ;
        final int widthSpecSize = MeasureSpec. getSize(widthMeasureSpec) ;
        final int heightSpecMode = MeasureSpec. getMode(heightMeasureSpec) ;
        final int heightSpecSize = MeasureSpec. getSize(heightMeasureSpec) ;
       
        int paddingLeft = getPaddingLeft() ;
        int paddingRight = getPaddingRight() ;
        int paddingTop = getPaddingTop() ;
        int paddingBottom = getPaddingBottom() ;
        int maxWidth = widthSpecSize - paddingLeft - paddingRight ;
        int newWidth = 0;
        int maxHeight = heightSpecSize - paddingTop - paddingBottom ;
        int newHeight = 0;
       
        // 未使用,计算minWidth minHeight,以及background的值
        // int suggestedWidth = getSuggestedMinimumWidth();
        // int suggestedHeight = getSuggestedMinimumHeight();
       
        int count = getChildCount();
        int rowIndex = 0;
        int rowMaxWidth = 0;
        if ((maxWidth > 0 && widthSpecMode != MeasureSpec.UNSPECIFIED)
                || (widthSpecMode == MeasureSpec. UNSPECIFIED)) {
            for (int i = 0; i < count ; i++) {
                View child = getChildAt(i) ;
                if (child.getVisibility() != View.GONE) {
                    List<View> views = mSparseViews.get(rowIndex);
                    Integer childMaxHeight = mSparseHeights .get(rowIndex);
                    if (views == null) {
                        views = new ArrayList<View>();
                        mSparseViews.put(rowIndex, views);
                    }
                    if (childMaxHeight == null) {
                        childMaxHeight = new Integer(0 );
                        mSparseHeights.put(rowIndex, childMaxHeight);
                    }
                   
                    int childWidth = child.getMeasuredWidth() ;
                    int childHeight = child.getMeasuredHeight() ;
                   
                    if (childHeight > childMaxHeight) {
                        mSparseHeights.put(rowIndex, childHeight);
                    }
                   
                    int rowChildCount = views.size() ;
                    if (widthSpecMode != MeasureSpec.UNSPECIFIED) {
                        int tempRowWidth = rowMaxWidth + childWidth
                                + (rowChildCount > 0 ? mHorizontalSpacing : 0) ;
                        if (rowChildCount <= 0 || tempRowWidth <= maxWidth) {
                            rowMaxWidth = tempRowWidth ;
                            views.add(child);
                        }
                        else {
                            rowIndex++ ;
                            views = new ArrayList<View>() ;
                            mSparseViews.put(rowIndex, views);
                            mSparseHeights.put(rowIndex, childHeight);
                            rowMaxWidth = childWidth;
                            views.add(child);
                        }
                    }
                    else {
                        rowMaxWidth += childWidth
                                + (rowChildCount > 0 ? mHorizontalSpacing : 0) ;
                        views.add(child);
                    }
                    newWidth = rowMaxWidth ;
                }
               
            }
           
            int rowCount = mSparseViews.size() ;
            if (widthSpecMode == MeasureSpec. AT_MOST) {
                if (rowCount <= 1) {
                    newWidth = Math. min(newWidth , maxWidth);
                }
                else {
                    newWidth = maxWidth ;
                }
            }
            else if (widthSpecMode == MeasureSpec.EXACTLY) {
                newWidth = maxWidth;
            }
        }
       
        int rowMaxHeight = 0;
        int rowCount = mSparseHeights.size();
        for ( int i = 0 ; i < rowCount; i++) {
            rowMaxHeight += mSparseHeights.get(i) + (i > 0 ? mVerticalSpacing : 0) ;
        }
        if (heightSpecMode == MeasureSpec.AT_MOST) {
            newHeight = Math.min(rowMaxHeight, maxHeight);
        }
        else if (heightSpecMode == MeasureSpec.EXACTLY) {
            newHeight = maxHeight;
        }
        else {
            newHeight = rowMaxHeight;
        }
        setMeasuredDimension(newWidth + paddingLeft + paddingLeft, newHeight + paddingTop
                + paddingBottom);
       
    }
   
    @Override
    protected void onLayout(boolean change, int left , int top, int right, int bottom) {
        int rowCount = mSparseHeights.size() ;
        int rowLeft = getPaddingLeft() ;
        int rowTop = getPaddingTop() ;
        for ( int rowIndex = 0 ; rowIndex < rowCount; rowIndex++) {
            List<View> views = mSparseViews.get(rowIndex) ;
            int childMaxHeight = mSparseHeights.get(rowIndex);
            int rowChildCount = views.size() ;
            int l = rowLeft ;
            for ( int i = 0 ; i < rowChildCount; i++) {
                View child = views.get(i);
                int childWidth = child.getMeasuredWidth();
                int childHeight = child.getMeasuredHeight();
                int t = rowTop + (childMaxHeight - childHeight) / 2;
                child.layout(l, t, l + childWidth , t + childHeight);
                l += childWidth + mHorizontalSpacing ;
            }
            rowTop += childMaxHeight + mVerticalSpacing;
        }
    }
   
    @Override
    protected void onDetachedFromWindow() {
        super .onDetachedFromWindow();
        mSparseViews .clear();
        mSparseHeights .clear();
    }
   
    @Override
    public void onClick(View v) {
        if (indexOfChild(v) >= 0) {
            setChildrenSelected(v, !v.isSelected()) ;
        }
    }
   
    @Override
    public void onChildViewAdded(View view, View child) {
       
    }
   
    @Override
    public void onChildViewRemoved(View view, View child) {
        if (view == this) {
            mTagStates .remove(child.getTag());
        }
    }
   
    public interface OnTagSelectedListener {
        public void onTagSelectedChange(Object tag, boolean selected);
    }

attrs

<declare-styleable name="TagLayout">
    <attr name= "android:horizontalSpacing" />
    <attr name= "android:verticalSpacing" />
    <attr name= "singleChoice" format="boolean" />
</declare-styleable>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值