2011-03-04 6 views
3

제목에 항목 안에있는보기를 클릭 할 때 항목의 정확한 위치를 알고 싶습니다.특정보기를 클릭하면 목록보기 내에서 항목의 위치를 ​​어떻게 얻을 수 있습니까?

가정 해 보겠습니다 I ArrayAdapter와에서의 getView() 메소드 내에서 다음 코드가 : 온 클릭() 나는, 클릭 브이보기를 알고,하지만 난의 위치를 ​​모르는 내

... 
holder = new ViewHolder(); 
holder.iconAction = (ImageView)convertView.findViewById (R.id.download_item_iconAction); 
holder.iconAction.setOnClickListener (new View.OnClickListener(){ 
    @Override 
    public void onClick (View v){ 
     //Item X is clicked 
    } 
}); 
... 

을 목.

트릭을 만들어 봅시다. getView()가 뷰를 생성 할 때 ViewHolder에서 위치를 저장하려고합니다 :

public View getView (int position, View convertView, ViewGroup parent){ 
    ViewHolder holder; 
    if (convertView == null){ 
     holder = new ViewHolder(); 
     holder.iconAction = (ImageView)convertView.findViewById (id); 
     holder.iconAction.setOnClickListener (new View.OnClickListener(){ 
      @Override 
      public void onClick (View v){ 
       int pos = (Integer)v.getTag(); 
      } 
     }); 
     holder.iconWait.setTag (position); 

     ... 
    }else{ 
     holder = (ViewHolder)convertView.getTag(); 
    } 

    ... 
} 

이 코드는 작동하지만 항상 그런 것은 아닙니다. 모든 항목을 보려면 목록을 스크롤해야만 뷰가 재활용됩니다. 목록에 10 개의 요소가 있고 5 개만 표시된다고 가정합니다 (보이는 의미 : 항목의 픽셀 행이 1 개인 경우이 항목을 볼 수 있음). 이제 아래로 스크롤하면 여섯 번째 요소가 표시되지만 첫 번째 요소 (0)는 계속 표시됩니다. 조금 더 스크롤하면 첫 번째 요소가 숨겨지고 일곱 번째 요소가 나타납니다. 그러나이 새 요소의 뷰는 첫 번째 요소 (0)의 뷰입니다.
그래서 위치를 저장합니다 : 0, 1, 2, 3, 4 및 5. 일곱 번째 요소 (6)는 위치 0을 저장했습니다.

클릭 콜백을 얻을 수있는 또 다른 방법은 ListView에의 OnItemClickListener 리스너를 사용하고 있습니다 :

listView = getListView(); 
listView.setOnItemClickListener (new AdapterView.OnItemClickListener(){ 
    @Override 
    public void onItemClick (AdapterView<?> parentView, View childView, int position, long id){ 
     ... 
    } 
}); 

내가 아래로 스크롤하면 나는 정확한 위치를 얻을 수 있지만, 항목을 클릭 할 때 내가 콜백을받을 이러한 방법에 상관없이 클릭 된 자식보기.

감사합니다.

+0

이 매우 합법적 인 질문은 아래로 내려갔습니다. –

답변

7

거의 다 왔으므로 if/else 절 뒤에 태그를 설정하기 만하면됩니다. 이것은 태그가 새로 생성 될 때뿐만 아니라 뷰가 재활용 될 때 태그가 업데이트되도록합니다.

예컨대

if (convertView == null){ 
     holder = new ViewHolder(); 
     ... 
    }else{ 
     holder = (ViewHolder)convertView.getTag(); 
    } 
holder.iconWait.setTag (position); 
+0

Omg, 감사합니다. 그것은 놀랍게도 쉽습니다! –

0

holder.iconWait.setTag (position)을 if/then 문 외부로 이동하면 두 번째 대답 (요소에 태그를 설정 함)이 제대로 작동합니다. 즉, 새로 부풀려진 행뿐만 아니라 재활용 행에도 태그를 설정해야합니다. 사람.

+1

첫 번째 장소에서 ViewHolder/태그 메커니즘을 사용해야하는 이유가 직접 문제를 해결합니다. –

+0

실제로는 - 행을 채울 때마다 새 onclick 수신기를 할당하는 최종 변수 솔루션이 있습니다. 단지 생성 된 것이 아니라). 이것은보기가 스크롤 될 때 많은 가비지 콜렉션을 발생시킬 것이므로 나쁜 아이디어입니다. 확실히 간단하지만 사용자 환경을 다소 저하시킬 수 있습니다 (특히 비 동시 GC가있는 2.3 이전 전화의 경우). 초기 행 인플레이션에서만 onClick 수신기를 설정 한 다음 새 클릭 수신기를 할당하지 않고 태그를 설정하는 것이 더 효율적입니다. –

3

로컬 익명 클래스 최종 로컬 변수를 참조 할 수있다.

이 읽도록 getView() 방법을 변경하여 최종 position합니다

public View getView (final int position, View convertView, ViewGroup parent) { 

을 한 다음은 OnClickListener 내에서 위치를 참조 할 수 있습니다

holder.iconAction.setOnClickListener (new View.OnClickListener(){ 
    @Override 
    public void onClick (View v){ 
     ... use position here ... 
    } 
}); 
+2

이 작업은 convertView가 null인지 여부에 관계없이 수행해야하므로 if (convertView == null) 문 외부로 이동해야합니다. –

+1

이것은 태그 지정보기보다 간단하지만 모든 getView() 호출 (초기 인플레이션이 아님)에 새 OnClick 수신기를 할당하면 비효율적이며 불필요한 GC 호출이 발생할 수 있으며 스크롤 성능이 어느 정도 저하 될 수 있습니다. –

0

나는 또한에 전달하는 다른 데이터를 추가하는 데 필요한 onClick 또한 문자열로도 작업했습니다.

holder.iconWait.setTag ("String data here"); 
관련 문제