Answers:
假设您生成了一堆相似的视图。您可以分别OnClickListener
为每个视图设置一个:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
然后,onClick
即使它们执行类似的操作,也必须为每个视图创建唯一的方法,例如:
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
这是因为onClick
只有一个参数a View
,并且它必须从封闭范围中的实例变量或最终局部变量获取其他信息。我们真正想要的是从视图本身获取信息。
输入getTag
/ setTag
:
button1.setTag(1);
button2.setTag(2);
现在,我们可以对每个按钮使用相同的OnClickListener:
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
基本上,这是一种让视图具有记忆力的方法。
public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }
应对颜色部分有用。20只是用于验证View位置的占位符。
我想补充几句话。
尽管get/setTag(Object)
在ViewHolder模式的特定情况下使用似乎很有用,但我建议在其他情况下使用之前再三考虑。几乎总是有另一个具有更好设计的解决方案。
主要原因是这样的代码很快变得不被支持。
对于其他开发人员而言,您打算将其存储为标签的内容并不明显。这些方法setTag/getTag
根本不是描述性的。
它只存储一个Object
,需要时强制将其强制转换getTag
。当您决定更改标记中存储的对象的类型时,以后可能会遇到意外崩溃。
这是一个真实的故事:我们有一个很大的项目,其中包含许多适配器,带有视图的异步操作等。一个开发人员决定set/getTag
在他的代码部分中这样做,但是另一位开发人员已经将标签设置为此视图。最后,某人找不到自己的标签,感到非常困惑。我们花了几个小时才能找到该错误。
setTag(int key, Object tag)
看起来好多了,因为您可以为每个标签生成唯一的密钥(使用id资源),但是对于Android <4.0,存在明显的限制。从Lint docs:
在Android 4.0之前,View.setTag(int,Object)的实现会将对象存储在静态映射中,在其中强烈引用了值。这意味着,如果对象包含指向上下文的任何引用,则上下文(指向几乎所有其他内容)将泄漏。如果传递视图,则该视图将提供对创建该视图的上下文的引用。同样,视图持有者通常包含一个视图,并且光标有时也与视图相关联。
这对于自定义ArrayAdapter
使用非常有用。这是某种优化。有setTag
用作参考对象上布局的某些部分的引用(即在显示ListView
)代替findViewById
。
static class ViewHolder {
TextView tvPost;
TextView tvDate;
ImageView thumb;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.postitem, null);
ViewHolder vh = new ViewHolder();
vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
convertView.setTag(vh);
}
....................
}
与ID不同,标签不用于标识视图。标签本质上是可以与视图关联的额外信息。它们最常用于方便地在视图本身中存储与视图相关的数据,而不是将它们放在单独的结构中。
参考:http : //developer.android.com/reference/android/view/View.html
当您拥有ListView并想要回收/重用视图时,设置TAG确实很有用。这样,ListView就变得与更新的RecyclerView非常相似。
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if ( convertView == null )
{
/* There is no view at this position, we create a new one.
In this case by inflating an xml layout */
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
convertView.setTag (holder);
}
else
{
/* We recycle a View that already exists */
holder = (ViewHolder) convertView.getTag ();
}
// Once we have a reference to the View we are returning, we set its values.
// Here is where you should set the ToggleButton value for this item!!!
holder.toggleOk.setChecked( mToggles.get( position ) );
return convertView;
}