답변:
비슷한 뷰를 생성한다고 가정 해 보겠습니다. 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 resources 사용 ) Android <4.0에는 상당한 제한이 있습니다. 린트 문서에서 :
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
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;
}