Odpowiedzi:
Załóżmy, że generujesz kilka podobnych widoków. Możesz ustawić OnClickListener
osobno dla każdego widoku:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
Następnie musisz utworzyć unikalną onClick
metodę dla każdego widoku, nawet jeśli robią podobne rzeczy, takie jak:
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
Jest tak, ponieważ onClick
ma tylko jeden parametr, a View
, i musi uzyskać inne informacje ze zmiennych instancji lub końcowych zmiennych lokalnych w obejmujących zakresach. Tak naprawdę chcemy uzyskać informacje z samych widoków .
Wpisz getTag
/ setTag
:
button1.setTag(1);
button2.setTag(2);
Teraz możemy użyć tego samego OnClickListener dla każdego przycisku:
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
Jest to w zasadzie sposób, by widoki miały wspomnienia .
public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }
powinien załatwić sprawę z częścią kolorową. 20 jest tylko symbolem zastępczym dla pozycji sprawdzającej poprawność Twojego Widoku.
Chciałbym dodać kilka słów.
Chociaż używanie get/setTag(Object)
wydaje się być bardzo przydatne w szczególnym przypadku wzorca ViewHolder, zalecam zastanowić się dwa razy przed użyciem go w innych przypadkach. Prawie zawsze istnieje inne rozwiązanie o lepszym designie.
Głównym powodem jest to, że taki kod dość szybko staje się nieobsługiwany.
Dla innych programistów nie jest oczywiste, co zaprojektowałeś do przechowywania jako znacznik w widoku. Metody setTag/getTag
w ogóle nie mają charakteru opisowego.
Po prostu przechowuje plik Object
, który trzeba rzucić, kiedy chcesz getTag
. Nieoczekiwane awarie mogą wystąpić później, gdy zdecydujesz się zmienić typ przechowywanego obiektu w znaczniku.
Oto prawdziwa historia: mieliśmy całkiem duży projekt z dużą ilością adapterów, operacji asynchronicznych z widokami i tak dalej. Jeden programista postanowił set/getTag
w swojej części kodu, ale inny już ustawił tag w tym widoku. W końcu ktoś nie mógł znaleźć własnej metki i był bardzo zdezorientowany. Znalezienie błędu kosztowało nas kilka godzin.
setTag(int key, Object tag)
wygląda o wiele lepiej, ponieważ możesz wygenerować unikalne klucze dla każdego tagu (używając zasobów identyfikatora ), ale jest znaczące ograniczenie dla Androida <4.0. Z dokumentów Lint:
W wersjach wcześniejszych niż Android 4.0 implementacja View.setTag (int, Object) przechowywałaby obiekty w mapie statycznej, gdzie wartości były silnie przywoływane. Oznacza to, że jeśli obiekt zawiera odniesienia do kontekstu, kontekst (który wskazuje na prawie wszystko inne) wycieknie. Jeśli przejdziesz widok, widok zawiera odniesienie do kontekstu, który go utworzył. Podobnie, uchwyty widoków zazwyczaj zawierają widok, a kursory czasami są również powiązane z widokami.
Możemy używać setTag()
i getTag()
ustawiać i uzyskiwać niestandardowe obiekty zgodnie z naszymi wymaganiami. setTag()
Metoda wymaga argumentu typu Object
i getTag()
zwraca Object
.
Na przykład,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Jest to bardzo przydatne do niestandardowego ArrayAdapter
korzystania. To jest jakaś optymalizacja. Jest setTag
używany jako odniesienie do obiektu odniesienia na niektórych częściach układu (czyli wyświetlanie w ListView
) zamiast 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);
}
....................
}
W przeciwieństwie do identyfikatorów tagi nie są używane do identyfikowania widoków. Tagi są w zasadzie dodatkową informacją, którą można powiązać z widokiem. Są one najczęściej używane jako wygoda do przechowywania danych związanych z widokami w samych widokach, zamiast umieszczania ich w osobnej strukturze.
Odniesienie: http://developer.android.com/reference/android/view/View.html
Ustawienie TAG jest bardzo przydatne, gdy masz ListView i chcesz odtworzyć / ponownie wykorzystać widoki. W ten sposób ListView staje się bardzo podobny do nowszego 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;
}