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
- android 一些通用view(2)
- android 一些通用View
- android 通用view封装
- Android自定义View之TitleBar,通用标题栏
- android view手势冲突的通用解决方法
- android view手势冲突的通用解决方法
- Android view 相关一些基础
- Android View的一些位置
- android-view(2)
- View类通用模板(C#)
- 通用软件产品化的一些想法(2)
- Android所有View通用下拉刷新上拉加载控件
- Android View 高级框架一 Builder模式打造通用TitleBar
- Android View 高级框架二 Builder模式打造通用对话框
- Android自定义view(2)
- android 自定义 View(2)
- android view的一些常用触发方法
- Android surface view 的一些使用
- C++中修改文件夹名以及文件名
- Versions的简单配置
- JavaScript高级程序设计之DOM之节点层次之Element类型第10.1.3讲
- 圆方参数化之-- 抽屉导轨五金的入库
- 设计模式----Proxy(代理)模式
- android 一些通用view(2)
- 链接样式表和导入样式区别
- 子框架中使父框架中滚动条置顶
- 2015.10.31的NOIP模拟赛
- HDU1009
- 静态语言和动态语言的区别
- 数据结构与算法经典习题解答
- Design TabLayout+ViewPager+Fragment,实现选中请求数据+缓存
- sae中配置weiphp,修复图片上传问题