版本号:1.0
日期:2014.7.24
版权:© 2014 kince 转载注明出处
  
  在有的应用中可能须要设置一些标签来方便用去去查询某些信息,比方手机助手或者购物软件之类都会有一些标签。对于软件开发初期来说,直接使用TextView、Button实现是最为简单的一种方式。可是这样的方法也有其局限性,比方不能控制换行、耦合性低等缺点。所以除了解决这些问题之外,最好能够封装一个类库出来,方便以后使用。
  首先新建一个Tag类,
import java.io.Serializable;

public class Tag implements Serializable {

      /**
*
*/
private static final long serialVersionUID = 2684657309332033242L; private int backgroundResId ;
private int id ;
private boolean isChecked ;
private int leftDrawableResId ;
private int rightDrawableResId ;
private String title; public Tag() { } public Tag( int paramInt, String paramString) {
this .id = paramInt;
this .title = paramString;
} public int getBackgroundResId() {
return this .backgroundResId ;
} public int getId() {
return this .id ;
} public int getLeftDrawableResId() {
return this .leftDrawableResId ;
} public int getRightDrawableResId() {
return this .rightDrawableResId ;
} public String getTitle() {
return this .title ;
} public boolean isChecked() {
return this .isChecked ;
} public void setBackgroundResId( int paramInt) {
this .backgroundResId = paramInt;
} public void setChecked( boolean paramBoolean) {
this .isChecked = paramBoolean;
} public void setId(int paramInt) {
this .id = paramInt;
} public void setLeftDrawableResId( int paramInt) {
this .leftDrawableResId = paramInt;
} public void setRightDrawableResId( int paramInt) {
this .rightDrawableResId = paramInt;
} public void setTitle(String paramString) {
this .title = paramString;
}
}
  这个类封装了标签视图的背景图片资源、id、是否check等。
  然后新建TagView类,继承自ToggleButton,
import com.niceapp.lib.tagview.R;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ToggleButton; public class TagView extends ToggleButton { private boolean mCheckEnable = true; public TagView(Context paramContext) {
super (paramContext);
init();
} public TagView(Context paramContext, AttributeSet paramAttributeSet) {
super (paramContext, paramAttributeSet);
init();
} public TagView(Context paramContext, AttributeSet paramAttributeSet,
int paramInt) {
super (paramContext, paramAttributeSet, 0);
init();
} private void init() {
setTextOn( null );
setTextOff( null );
setText( "" );
setBackgroundResource(R.drawable. tag_bg );
} public void setCheckEnable( boolean paramBoolean) {
this .mCheckEnable = paramBoolean;
if (!this .mCheckEnable ) {
super .setChecked( false);
}
} public void setChecked( boolean paramBoolean) {
if (this .mCheckEnable ) {
super .setChecked(paramBoolean);
}
}
}

这个TagView就是标签视图,标签信息由他来显示。对应的xml文件例如以下,tag.xml:

<? xml version= "1.0" encoding = "utf-8"?>
< com.niceapp.lib.tagview.widget.TagView xmlns:android ="http://schemas.android.com/apk/res/android"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:drawablePadding= "5.0dip"
android:minHeight= "0.0dip"
android:paddingBottom= "4.5dip"
android:paddingLeft= "20.0dip"
android:paddingRight= "20.0dip"
android:paddingTop= "4.5dip"
android:textColor= "#ff000000"
android:textSize= "16.0sp" />
显演示样例如以下:
 
 在github上有一个android-flowlayout控件,它是依据子视图的大小来动态包裹视图,如图:
 
  因此,控制换行就能够利用这个控件去实现,无需反复发明轮子。android-flowlayout功能实现的类是FlowLayout,所以通过继承这个类来完毕标签控件的实现。
import java.util.ArrayList;
import java.util.List;
import com.niceapp.lib.tagview.R;
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CompoundButton; /**
* @author kince
*
*/
public class TagListView extends FlowLayout implements OnClickListener { private boolean mIsDeleteMode;
private OnTagCheckedChangedListener mOnTagCheckedChangedListener;
private OnTagClickListener mOnTagClickListener;
private int mTagViewBackgroundResId;
private int mTagViewTextColorResId;
private final List<Tag> mTags = new ArrayList<Tag>(); /**
* @param context
*/
public TagListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
} /**
* @param context
* @param attributeSet
*/
public TagListView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
// TODO Auto-generated constructor stub
init();
} /**
* @param context
* @param attributeSet
* @param defStyle
*/
public TagListView(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
// TODO Auto-generated constructor stub
init();
} @Override
public void onClick(View v) {
if ((v instanceof TagView)) {
Tag localTag = (Tag) v.getTag();
if (this.mOnTagClickListener != null) {
this.mOnTagClickListener.onTagClick((TagView) v, localTag);
}
}
} private void init() { } private void inflateTagView(final Tag t, boolean b) { TagView localTagView = (TagView) View.inflate(getContext(),
R.layout.tag, null);
localTagView.setText(t.getTitle());
localTagView.setTag(t); if (mTagViewTextColorResId <= 0) {
int c = getResources().getColor(R.color.blue);
localTagView.setTextColor(c); } if (mTagViewBackgroundResId <= 0) {
mTagViewBackgroundResId = R.drawable.tag_bg;
localTagView.setBackgroundResource(mTagViewBackgroundResId);
} localTagView.setChecked(t.isChecked());
localTagView.setCheckEnable(b);
if (mIsDeleteMode) {
int k = (int) TypedValue.applyDimension(1, 5.0F, getContext()
.getResources().getDisplayMetrics());
localTagView.setPadding(localTagView.getPaddingLeft(),
localTagView.getPaddingTop(), k,
localTagView.getPaddingBottom());
localTagView.setCompoundDrawablesWithIntrinsicBounds(0, 0,
R.drawable.forum_tag_close, 0);
}
if (t.getBackgroundResId() > 0) {
localTagView.setBackgroundResource(t.getBackgroundResId());
}
if ((t.getLeftDrawableResId() > 0) || (t.getRightDrawableResId() > 0)) {
localTagView.setCompoundDrawablesWithIntrinsicBounds(
t.getLeftDrawableResId(), 0, t.getRightDrawableResId(), 0);
}
localTagView.setOnClickListener(this);
localTagView
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(
CompoundButton paramAnonymousCompoundButton,
boolean paramAnonymousBoolean) {
t.setChecked(paramAnonymousBoolean);
if (TagListView.this.mOnTagCheckedChangedListener != null) {
TagListView.this.mOnTagCheckedChangedListener
.onTagCheckedChanged(
(TagView) paramAnonymousCompoundButton,
t);
}
}
});
addView(localTagView);
} public void addTag(int i, String s) {
addTag(i, s, false);
} public void addTag(int i, String s, boolean b) {
addTag(new Tag(i, s), b);
} public void addTag(Tag tag) {
addTag(tag, false);
} public void addTag(Tag tag, boolean b) {
mTags.add(tag);
inflateTagView(tag, b);
} public void addTags(List<Tag> lists) {
addTags(lists, false);
} public void addTags(List<Tag> lists, boolean b) {
for (int i = 0; i < lists.size(); i++) {
addTag((Tag) lists.get(i), b);
}
} public List<Tag> getTags() {
return mTags;
} public View getViewByTag(Tag tag) {
return findViewWithTag(tag);
} public void removeTag(Tag tag) {
mTags.remove(tag);
removeView(getViewByTag(tag));
} public void setDeleteMode(boolean b) {
mIsDeleteMode = b;
} public void setOnTagCheckedChangedListener(
OnTagCheckedChangedListener onTagCheckedChangedListener) {
mOnTagCheckedChangedListener = onTagCheckedChangedListener;
} public void setOnTagClickListener(OnTagClickListener onTagClickListener) {
mOnTagClickListener = onTagClickListener;
} public void setTagViewBackgroundRes(int res) {
mTagViewBackgroundResId = res;
} public void setTagViewTextColorRes(int res) {
mTagViewTextColorResId = res;
} public void setTags(List<? extends Tag> lists) {
setTags(lists, false);
} public void setTags(List<? extends Tag> lists, boolean b) {
removeAllViews();
mTags.clear();
for (int i = 0; i < lists.size(); i++) {
addTag((Tag) lists.get(i), b);
}
} public static abstract interface OnTagCheckedChangedListener {
public abstract void onTagCheckedChanged(TagView tagView, Tag tag);
} public static abstract interface OnTagClickListener {
public abstract void onTagClick(TagView tagView, Tag tag);
} }
  这个类最要的部分还是inflateTagView这种方法,它将TagView解析出来出来,然后显示出TagListView所要显示的标签。
  最后Activity的代码例如以下:
import java.util.ArrayList;
import java.util.List;
import com.niceapp.lib.tagview.widget.Tag;
import com.niceapp.lib.tagview.widget.TagListView;
import android.app.Activity;
import android.os.Bundle; public class MainActivity extends Activity { private TagListView mTagListView;
private final List<Tag> mTags = new ArrayList<Tag>();
private final String[] titles = { "安全必备", "音乐", "父母学", "上班族必备",
"360手机卫士", "QQ","输入法", "微信", "最美应用", "AndevUI", "蘑菇街" }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.select_tag_activity); mTagListView = (TagListView) findViewById(R.id.tagview);
setUpData();
mTagListView.setTags(mTags);
} private void setUpData() {
for (int i = 0; i < 10; i++) {
Tag tag = new Tag();
tag.setId(i);
tag.setChecked(true);
tag.setTitle(titles[i]);
mTags.add(tag);
}
}
}
真机显示效果例如以下:
  
  当然,这个TagView的外观还是能够自己设置的,包含字体、背景等等。

Android 标签控件的更多相关文章

  1. Android控件进阶-自定义流式布局和热门标签控件

    技术:Android+java   概述 在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧,类 ...

  2. Android基本控件之Menus

    在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...

  3. VS2010/MFC编程入门之三十三(常用控件:标签控件Tab Control 下)

    上一节中鸡啄米讲了标签控件知识的上半部分,本节继续讲下半部分. 标签控件的创建 MFC为标签控件的操作提供了CTabCtrl类. 与之前的控件类似,创建标签控件可以在对话框模板中直接拖入Tab Con ...

  4. Kotlin 第一弹:自定义 ViewGroup 实现流式标签控件

    古人学问无遗力, 少壮工夫老始成.纸上得来终觉浅, 绝知此事要躬行. – 陆游 <冬夜读书示子聿> 上周 Google I/O 大会的召开,宣布了 Kotlin 语言正式成为了官方开发语言 ...

  5. 一个Demo让你掌握Android所有控件

    原文:一个Demo让你掌握Android所有控件 本文是转载收藏,侵删,出处:"安卓巴士"      下面给出实现各个组件的源代码: 1.下拉框实现--Spinner packag ...

  6. Android UI控件常用库汇总

    现在App的开发已经是非常成熟,涌现了一大批开源的工具.这些项目能够提高我们的搬砖效率.以下是一些在开发中比较常使用的控件和库. ListView WaveSwipeRefreshLayout 水滴效 ...

  7. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  8. VS2010-MFC(常用控件:标签控件Tab Control 下)

    转自:http://www.jizhuomi.com/software/207.html 上一节讲了标签控件知识的上半部分,本节继续讲下半部分. 标签控件的创建 MFC为标签控件的操作提供了CTabC ...

  9. android 基础控件(EditView、SeekBar等)的属性及使用方法

        android提供了大量的UI控件,本文将介绍TextView.ImageView.Button.EditView.ProgressBar.SeekBar.ScrollView.WebView ...

随机推荐

  1. [转载]node.js express 4.x 安装指南,没有自动配置环境变量的问题

    前几天express 推出了4.0,得知这个消息,自己尝试了一下,突然发现用以前的文档上的操作出现了各种问题.结果只能去看文档,现在在这个给大家分享下4.0版本的安装. 先说下如果需要用express ...

  2. substr(dirname(__FILE__))

    这是discuz中定义论坛安装根目录的一个常量.现在我们就来分析一下这个很简单但是非常实用的常量.     define('DISCUZ_ROOT', substr(dirname(__FILE__) ...

  3. codeforces 659E . New Reform 强连通

    题目链接 对于每一个联通块, 如果有一个强连通分量, 那么这个联通块对答案的贡献就是0. 否则对答案贡献是1. #include <iostream> #include <vecto ...

  4. [原创]obj-c编程16:键值编码(KVC)

    原文链接:obj-c编程16:键值编码(KVC) 我们可以借助obj-c中的键值编码(以后简称KVC,Key-Value Coding)来存取类的属性,通过指定所要访问的属性名字符串标示符,可以使用存 ...

  5. 异步流程控制库GoWithTheFlow

    异步流程控制库GoWithTheFlow 一个尾触发方式来控制异步流程的库, 有seq(顺序执行) par(同步执行) 两种方法 博客 http://notes.jetienne.com/2011/0 ...

  6. Oracle转移user表空间位置

    1:登录sqlplus sqlplus /nolog conn sys/bcc@gis as sysdba 2:修改表空间位offline alter tablespace users offline ...

  7. leetcode_question_115 Distinct Subsequences

    Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence ...

  8. C#时间格式之GMT时间的格式

    GMT:格林尼标准时间  北京时间=GMT时间+8小时 DataTime nowDate = DataTime.Now; nowDate.toString("r");    效果为 ...

  9. Linux前台的程序转到后台执行(关闭终端而不杀死命令)

    你是否经常遇到这样的情况,通过SSH或者终端putty连接到一台linux/unix机器,执行一个程序.一个脚本或者一条命令,但现在你需要关闭SSH或者终端,由于该该程序.脚本或者命令正在运行,一旦你 ...

  10. Deep Learning(深度学习)学习笔记整理系列之(三)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...