Відповіді:
Скажімо, ви формуєте купу схожих поглядів. Ви можете встановити 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 - це лише заповнювач місця для валідаційної позиції вашого представлення даних.
Я хотів би додати кілька слів.
Хоча використання get/setTag(Object)
здається дуже корисним у конкретному випадку шаблону ViewHolder, я рекомендую подумати двічі, перш ніж використовувати його в інших випадках. Майже завжди є ще одне рішення з кращим дизайном.
Основна причина полягає в тому, що подібний код стає швидко непідтримуваним.
Для інших розробників не очевидно, що ви планували зберігати як тег у представленні. Методи setTag/getTag
взагалі не є описовими.
Він просто зберігає таку Object
, яку потрібно передати, коли захочете getTag
. Пізніше ви можете отримати несподівані збої, коли вирішите змінити тип збереженого об’єкта в тезі.
Ось історія з реального життя: у нас був досить великий проект з великою кількістю адаптерів, операцій з асинхронізацією з видами тощо. Один розробник вирішив ввести set/getTag
свою частину коду, але інший вже встановив тег на цей вид. Зрештою, хтось не зміг знайти власний тег і дуже розгубився. Щоб знайти помилку нам коштувало кілька годин.
setTag(int key, Object tag)
виглядає набагато краще, тому що ви можете генерувати унікальні ключі для кожного тегу (використовуючи ресурси id ), але для Android <4.0 є суттєве обмеження. З Документів Lint:
До Android 4.0 реалізація View.setTag (int, Object) зберігала б об'єкти в статичній карті, де значення були чітко вказані. Це означає, що якщо об’єкт містить будь-які посилання, що вказують на контекст, контекст (який вказує на майже все інше) просочиться. Якщо ви переходите до перегляду, подання посилається на контекст, який його створив. Аналогічно, власники перегляду зазвичай містять подання, а курсори іноді також асоціюються з поданнями.
Ми можемо використовувати setTag()
та getTag()
встановлювати та отримувати власні об’єкти відповідно до нашої вимоги. setTag()
Метод приймає аргумент типу Object
, і getTag()
повертає Object
.
Наприклад,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Це дуже корисно для користувальницького 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);
}
....................
}
На відміну від ідентифікаторів, теги не використовуються для ідентифікації представлень. Теги - це, по суті, додаткова інформація, яка може бути пов’язана з переглядом. Вони найчастіше використовуються як зручність для зберігання даних, пов’язаних із переглядами, у самих поданнях, а не шляхом їх розміщення в окремій структурі.
Довідка: http://developer.android.com/reference/android/view/View.html
Налаштування TAG дуже корисно, коли у вас є ListView і хочете переробити / повторно використати представлення даних. Таким чином 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;
}