标签流控件
来源:互联网 发布:手机淘宝流量劫持 编辑:程序博客网 时间:2024/06/09 23:27
标签流LabelsView
自定义控件代码
public class LabelsView extends ViewGroup implements View.OnClickListener { private Context mContext; private ColorStateList mTextColor; private float mTextSize; private int mLabelBgResId; private int mTextPaddingLeft; private int mTextPaddingTop; private int mTextPaddingRight; private int mTextPaddingBottom; private int mWordMargin; private int mLineMargin; private SelectType mSelectType; private int mMaxSelect; private ArrayList<String> mLabels = new ArrayList<>(); //保存选中的label的位置 private ArrayList<Integer> mSelectLabels = new ArrayList<>(); private OnLabelClickListener mLabelClickListener; private OnLabelSelectChangeListener mLabelSelectChangeListener; /** * Label的选择类型 */ public enum SelectType { //不可选中,也不响应选中事件回调。(默认) NONE(1), //单选 SINGLE(2), //多选 MULTI(3); int value; SelectType(int value) { this.value = value; } static SelectType get(int value) { switch (value) { case 1: return NONE; case 2: return SINGLE; case 3: return MULTI; } return NONE; } } public LabelsView(Context context) { super(context); mContext = context; } public LabelsView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; getAttrs(context, attrs); } public LabelsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; getAttrs(context, attrs); } private void getAttrs(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.labels_view); int type = mTypedArray.getInt(R.styleable.labels_view_selectType, 1); mSelectType = SelectType.get(type); mMaxSelect = mTypedArray.getInteger(R.styleable.labels_view_maxSelect, 0); mTextColor = mTypedArray.getColorStateList(R.styleable.labels_view_labelTextColor); mTextSize = mTypedArray.getDimension(R.styleable.labels_view_labelTextSize, sp2px(context, 14)); mTextPaddingLeft = mTypedArray.getDimensionPixelOffset( R.styleable.labels_view_labelTextPaddingLeft, 0); mTextPaddingTop = mTypedArray.getDimensionPixelOffset( R.styleable.labels_view_labelTextPaddingTop, 0); mTextPaddingRight = mTypedArray.getDimensionPixelOffset( R.styleable.labels_view_labelTextPaddingRight, 0); mTextPaddingBottom = mTypedArray.getDimensionPixelOffset( R.styleable.labels_view_labelTextPaddingBottom, 0); mLineMargin = mTypedArray.getDimensionPixelOffset(R.styleable.labels_view_lineMargin, 0); mWordMargin = mTypedArray.getDimensionPixelOffset(R.styleable.labels_view_wordMargin, 0); mLabelBgResId = mTypedArray.getResourceId(R.styleable.labels_view_labelBackground, 0); mTypedArray.recycle(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int count = getChildCount(); int maxWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); int contentHeight = 0; //记录内容的高度 int lineWidth = 0; //记录行的宽度 int maxLineWidth = 0; //记录最宽的行宽 int maxItemHeight = 0; //记录一行中item高度最大的高度 boolean begin = true; //是否是行的开头 for (int i = 0; i < count; i++) { View view = getChildAt(i); measureChild(view, widthMeasureSpec, heightMeasureSpec); if (maxWidth < lineWidth + view.getMeasuredWidth()) { contentHeight += mLineMargin; contentHeight += maxItemHeight; maxItemHeight = 0; maxLineWidth = Math.max(maxLineWidth, lineWidth); lineWidth = 0; begin = true; } maxItemHeight = Math.max(maxItemHeight, view.getMeasuredHeight()); if (!begin) { lineWidth += mWordMargin; } else { begin = false; } lineWidth += view.getMeasuredWidth(); } contentHeight += maxItemHeight; maxLineWidth = Math.max(maxLineWidth, lineWidth); setMeasuredDimension(measureWidth(widthMeasureSpec, maxLineWidth), measureHeight(heightMeasureSpec, contentHeight)); } private int measureWidth(int measureSpec, int contentWidth) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = contentWidth + getPaddingLeft() + getPaddingRight(); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } result = Math.max(result, getSuggestedMinimumWidth()); return result; } private int measureHeight(int measureSpec, int contentHeight) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = contentHeight + getPaddingTop() + getPaddingBottom(); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } result = Math.max(result, getSuggestedMinimumHeight()); return result; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int x = getPaddingLeft(); int y = getPaddingTop(); int contentWidth = right - left; int maxItemHeight = 0; int count = getChildCount(); for (int i = 0; i < count; i++) { View view = getChildAt(i); if (contentWidth < x + view.getMeasuredWidth() + getPaddingRight()) { x = getPaddingLeft(); y += mLineMargin; y += maxItemHeight; maxItemHeight = 0; }// if ((i+1)%3==0){// x = getPaddingLeft();// y += mLineMargin;// y += maxItemHeight;// maxItemHeight = 0;// } view.layout(x, y, x + view.getMeasuredWidth(), y + view.getMeasuredHeight()); x += view.getMeasuredWidth(); x += mWordMargin; maxItemHeight = Math.max(maxItemHeight, view.getMeasuredHeight()); } } /* 用于保存View的信息的key */ private static final String KEY_SUPER_STATE = "key_super_state"; private static final String KEY_TEXT_COLOR_STATE = "key_text_color_state"; private static final String KEY_TEXT_SIZE_STATE = "key_text_size_state"; private static final String KEY_BG_RES_ID_STATE = "key_bg_res_id_state"; private static final String KEY_PADDING_STATE = "key_padding_state"; private static final String KEY_WORD_MARGIN_STATE = "key_word_margin_state"; private static final String KEY_LINE_MARGIN_STATE = "key_line_margin_state"; private static final String KEY_SELECT_TYPE_STATE = "key_select_type_state"; private static final String KEY_MAX_SELECT_STATE = "key_max_select_state"; private static final String KEY_LABELS_STATE = "key_labels_state"; private static final String KEY_SELECT_LABELS_STATE = "key_select_labels_state"; @Override public Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); //保存父类的信息 bundle.putParcelable(KEY_SUPER_STATE, super.onSaveInstanceState()); //保存标签文字颜色 if (mTextColor != null) { bundle.putParcelable(KEY_TEXT_COLOR_STATE, mTextColor); } //保存标签文字大小 bundle.putFloat(KEY_TEXT_SIZE_STATE, mTextSize); //保存标签背景 bundle.putInt(KEY_BG_RES_ID_STATE, mLabelBgResId); //保存标签内边距 bundle.putIntArray(KEY_PADDING_STATE, new int[]{mTextPaddingLeft, mTextPaddingTop, mTextPaddingRight, mTextPaddingBottom}); //保存标签间隔 bundle.putInt(KEY_WORD_MARGIN_STATE, mWordMargin); //保存行间隔 bundle.putInt(KEY_LINE_MARGIN_STATE, mLineMargin); //保存标签的选择类型 bundle.putInt(KEY_SELECT_TYPE_STATE, mSelectType.value); //保存标签的最大选择数量 bundle.putInt(KEY_MAX_SELECT_STATE, mMaxSelect); //保存标签列表 if (!mLabels.isEmpty()) { bundle.putStringArrayList(KEY_LABELS_STATE, mLabels); } //保存已选择的标签列表 if (!mSelectLabels.isEmpty()) { bundle.putIntegerArrayList(KEY_SELECT_LABELS_STATE, mSelectLabels); } return bundle; } @Override public void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; //恢复父类信息 super.onRestoreInstanceState(bundle.getParcelable(KEY_SUPER_STATE)); //恢复标签文字颜色 ColorStateList color = bundle.getParcelable(KEY_TEXT_COLOR_STATE); if (color != null) { setLabelTextColor(color); } //恢复标签文字大小 setLabelTextSize(bundle.getFloat(KEY_TEXT_SIZE_STATE, mTextSize)); //恢复标签背景 int resId = bundle.getInt(KEY_BG_RES_ID_STATE, mLabelBgResId); if (resId != 0) { setLabelBackgroundResource(resId); } //恢复标签内边距 int[] padding = bundle.getIntArray(KEY_PADDING_STATE); if (padding != null && padding.length == 4) { setLabelTextPadding(padding[0], padding[1], padding[2], padding[3]); } //恢复标签间隔 setWordMargin(bundle.getInt(KEY_WORD_MARGIN_STATE, mWordMargin)); //恢复行间隔 setLineMargin(bundle.getInt(KEY_LINE_MARGIN_STATE, mLineMargin)); //恢复标签的选择类型 setSelectType(SelectType.get(bundle.getInt(KEY_SELECT_TYPE_STATE, mSelectType.value))); //恢复标签的最大选择数量 setMaxSelect(bundle.getInt(KEY_MAX_SELECT_STATE, mMaxSelect)); //恢复标签列表 ArrayList<String> labels = bundle.getStringArrayList(KEY_LABELS_STATE); if (labels != null && !labels.isEmpty()) { setLabels(labels); } //恢复已选择的标签列表 ArrayList<Integer> selectLabel = bundle.getIntegerArrayList(KEY_SELECT_LABELS_STATE); if (selectLabel != null && !selectLabel.isEmpty()) { int size = selectLabel.size();// int[] positions = new int[size];// for (int i = 0; i < size; i++) {// positions[i] = selectLabel.get(i);// } ArrayList<Integer> positions=new ArrayList<>(); for (int i = 0; i < size; i++) { positions.add(selectLabel.get(i)) ; } setSelects(positions); } return; } super.onRestoreInstanceState(state); } /** * 设置标签列表 * * @param labels */ public void setLabels(ArrayList<String> labels) { //清空原有的标签 clearAllSelect(); removeAllViews(); mLabels.clear(); if (labels != null) { mLabels.addAll(labels); int size = labels.size(); for (int i = 0; i < size; i++) { addLabel(labels.get(i), i); } } } /** * 获取标签列表 * * @return */ public ArrayList<String> getLabels() { return mLabels; } public void Add(String label){ mLabels.add(label); } private void addLabel(String text, int position) { final TextView label = new TextView(mContext); label.setPadding(mTextPaddingLeft, mTextPaddingTop, mTextPaddingRight, mTextPaddingBottom); label.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); label.setTextColor(mTextColor != null ? mTextColor : ColorStateList.valueOf(0xFF000000)); label.setText(text); if (mLabelBgResId != 0) { label.setBackgroundResource(mLabelBgResId); } //label通过tag保存自己的位置(position) label.setTag(position); label.setOnClickListener(this); addView(label); } @Override public void onClick(View v) { if (v instanceof TextView) { TextView label = (TextView) v; if (mSelectType != SelectType.NONE) { if (label.isSelected()) { setLabelSelect(label, false); } else if (mSelectType == SelectType.SINGLE) { clearAllSelect(); setLabelSelect(label, true); } else if (mSelectType == SelectType.MULTI && (mMaxSelect <= 0 || mMaxSelect > mSelectLabels.size())) { setLabelSelect(label, true); } } if (mLabelClickListener != null) { mLabelClickListener.onLabelClick(label, label.getText().toString(), (int) v.getTag()); } } } private void setLabelSelect(TextView label, boolean isSelect) { if (label.isSelected() != isSelect) { label.setSelected(isSelect); if (isSelect) { mSelectLabels.add((Integer) label.getTag()); } else { mSelectLabels.remove((Integer) label.getTag()); } if (mLabelSelectChangeListener != null) { mLabelSelectChangeListener.onLabelSelectChange(label, label.getText().toString(), isSelect, (int) label.getTag()); } } } /** * 取消所有选中的label */ public void clearAllSelect() { int count = getChildCount(); for (int i = 0; i < count; i++) { setLabelSelect((TextView) getChildAt(i), false); } mSelectLabels.clear(); } /** * 设置选中label * * @param positions */ public void setSelects(ArrayList<Integer> positions) { if (mSelectType != SelectType.NONE) { ArrayList<TextView> selectLabels = new ArrayList<>(); int count = getChildCount(); int size = mSelectType == SelectType.SINGLE ? 1 : mMaxSelect; for (int p : positions) { if (p < count) { TextView label = (TextView) getChildAt(p); if (!selectLabels.contains(label)) { setLabelSelect(label, true); selectLabels.add(label); } if (size > 0 && selectLabels.size() == size) { break; } } } for (int i = 0; i < count; i++) { TextView label = (TextView) getChildAt(i); if (!selectLabels.contains(label)) { setLabelSelect(label, false); } } } } /** * 获取选中的label * * @return */ public ArrayList<Integer> getSelectLabels() { return mSelectLabels; } /** * 设置标签背景 * * @param resId */ public void setLabelBackgroundResource(int resId) { if (mLabelBgResId != resId) { mLabelBgResId = resId; int count = getChildCount(); for (int i = 0; i < count; i++) { TextView label = (TextView) getChildAt(i); label.setBackgroundResource(mLabelBgResId); } } } /** * 设置标签内边距 * * @param left * @param top * @param right * @param bottom */ public void setLabelTextPadding(int left, int top, int right, int bottom) { if (mTextPaddingLeft != left || mTextPaddingTop != top || mTextPaddingRight != right || mTextPaddingBottom != bottom) { mTextPaddingLeft = left; mTextPaddingTop = top; mTextPaddingRight = right; mTextPaddingBottom = bottom; int count = getChildCount(); for (int i = 0; i < count; i++) { TextView label = (TextView) getChildAt(i); label.setPadding(left, top, right, bottom); } } } public int getTextPaddingLeft() { return mTextPaddingLeft; } public int getTextPaddingTop() { return mTextPaddingTop; } public int getTextPaddingRight() { return mTextPaddingRight; } public int getTextPaddingBottom() { return mTextPaddingBottom; } /** * 设置标签的文字大小(单位是px) * * @param size */ public void setLabelTextSize(float size) { if (mTextSize != size) { mTextSize = size; int count = getChildCount(); for (int i = 0; i < count; i++) { TextView label = (TextView) getChildAt(i); label.setTextSize(TypedValue.COMPLEX_UNIT_PX, size); } } } public float getLabelTextSize() { return mTextSize; } /** * 设置标签的文字颜色 * * @param color */ public void setLabelTextColor(int color) { setLabelTextColor(ColorStateList.valueOf(color)); } /** * 设置标签的文字颜色 * * @param color */ public void setLabelTextColor(ColorStateList color) { mTextColor = color; int count = getChildCount(); for (int i = 0; i < count; i++) { TextView label = (TextView) getChildAt(i); label.setTextColor(mTextColor != null ? mTextColor : ColorStateList.valueOf(0xFF000000)); } } public ColorStateList getLabelTextColor() { return mTextColor; } /** * 设置行间隔 */ public void setLineMargin(int margin) { if (mLineMargin != margin) { mLineMargin = margin; requestLayout(); } } public int getLineMargin() { return mLineMargin; } /** * 设置标签的间隔 */ public void setWordMargin(int margin) { if (mWordMargin != margin) { mWordMargin = margin; requestLayout(); } } public int getWordMargin() { return mWordMargin; } /** * 设置标签的选择类型 * * @param selectType */ public void setSelectType(SelectType selectType) { if (mSelectType != selectType) { mSelectType = selectType; //选择类型发生改变,就要恢复到初始状态。 clearAllSelect(); } } public SelectType getSelectType() { return mSelectType; } /** * 设置最大的选择数量 * * @param maxSelect */ public void setMaxSelect(int maxSelect) { if (mMaxSelect != maxSelect) { mMaxSelect = maxSelect; if (mSelectType == SelectType.MULTI) { //最大选择数量发生改变,就要恢复到初始状态。 clearAllSelect(); } } } public int getMaxSelect() { return mMaxSelect; } /** * 设置标签的点击监听 * * @param l */ public void setOnLabelClickListener(OnLabelClickListener l) { mLabelClickListener = l; } /** * 设置标签的选择监听 * * @param l */ public void setOnLabelSelectChangeListener(OnLabelSelectChangeListener l) { mLabelSelectChangeListener = l; } /** * sp转px */ public static int sp2px(Context context, float spVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, context.getResources().getDisplayMetrics()); } public interface OnLabelClickListener { void onLabelClick(View label, String labelText, int position); } public interface OnLabelSelectChangeListener { void onLabelSelectChange(View label, String labelText, boolean isSelect, int position); }}
布局
<LabelsView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/labels" android:layout_width="match_parent" android:layout_height="wrap_content" app:labelBackground="@drawable/label_bg" //标签的背景 app:labelTextColor="@drawable/label_text_color" //标签的字体颜色 可以是一个颜色值 app:labelTextSize="14sp" //标签的字体大小 app:labelTextPaddingBottom="5dp" //标签的上下左右边距 app:labelTextPaddingLeft="10dp" app:labelTextPaddingRight="10dp" app:labelTextPaddingTop="5dp" app:lineMargin="10dp" //行与行的距离 app:wordMargin="10dp" //标签与标签的距离 app:selectType="SINGLE" //标签的选择类型 有单选、多选、不可选三种类型 app:maxSelect="5" /> //标签的最大选择数量,只有多选的时候才有用,0为不限数量
监听
//标签的点击监听labelsView.setOnLabelClickListener(new LabelsView.OnLabelClickListener() { @Override public void onLabelClick(View label, String labelText, int position) { //label是被点击的标签,labelText是标签的文字,position是标签的位置。 }});//标签的选中监听labelsView.setOnLabelSelectChangeListener(new LabelsView.OnLabelSelectChangeListener() { @Override public void onLabelSelectChange(View label, String labelText, boolean isSelect, int position) { //label是被点击的标签,labelText是标签的文字,isSelect是是否选中,position是标签的位置。 }});
常用方法
//设置选中标签。//positions是个可变类型,表示被选中的标签的位置。//比喻labelsView.setSelects(1,2,5);选中第1,3,5个标签。如果是单选的话,只有第一个参数有效。public void setSelects(int... positions);//获取选中的标签。返回的是一个Integer的数组,表示被选中的标签的下标。如果没有选中,数组的size等于0。public ArrayList<Integer> getSelectLabels();//取消所有选中的标签。public void clearAllSelect();//设置标签的选择类型,有NONE、SINGLE和MULTI三种类型。public void setSelectType(SelectType selectType);//设置最大的选择数量,只有selectType等于MULTI是有效。public void setMaxSelect(int maxSelect);//设置标签背景public void setLabelBackgroundResource(int resId);//设置标签的文字颜色public void setLabelTextColor(int color);public void setLabelTextColor(ColorStateList color);//设置标签的文字大小(单位是px)public void setLabelTextSize(float size);//设置标签内边距public void setLabelTextPadding(int left, int top, int right, int bottom);//设置行间隔public void setLineMargin(int margin);//设置标签的间隔public void setWordMargin(int margin);
代码来自 博客:donkingliang,本人微改后使用,效果不错,感谢donkingliang!
阅读全文
0 0
- 标签流控件
- "-"标签控件(CTableCtrl)控件.
- Android流式标签布局,自定义标签控件tagView
- Android标签流控件的实现
- Android自定义流式标签控件
- VC++标签控件之图像标签控件
- 标签与控件fileupload
- 标签控件的使用
- SWT的标签控件
- 标签页控件
- 使用标签控件Tab
- QT控件之标签
- libgbx 控件之标签
- struts使用时间标签控件
- JavaFX - UI控件 - 标签
- Android 标签控件
- Android 标签控件
- Android 标签控件
- 基于php常用函数总结(数组,字符串,时间,文件操作)
- Magic Touch 中的手势识别(一)
- 遍历HashMap值
- BZOJ 1307 [ZJOI2008]生日聚会Party
- <mvc:default-servlet-handler />不能同时访问静态资源和动态资源的问题
- 标签流控件
- JQ常用正则
- error while loading shared libraries: libevent-2.1.so.6 的解决办法
- 敏感字过滤
- 【Java并发学习】之线程的同步
- /etc/inittab配置文件
- BaseRecyclerViewAdapterHelper源码解读(八) 空布局
- FreeRTOS之列表和列表项
- 无领导小组讨论如何带飞全组