android 一些通用view(2)

来源:互联网 发布:mac 安装qq五笔输入法 编辑:程序博客网 时间:2024/06/08 05:52

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