2012-11-08 8 views
38

Android listviews의 효율성을 극대화하려면 화면에 맞추기 위해 필요한만큼 많은 '행'보기 만 있어야한다는 것을 알았습니다. 보기가 화면에서 벗어나면 convertView이 null인지 아닌지 확인하면서 getView 메소드에서보기를 다시 사용해야합니다.두 개의 다른 레이아웃으로 Android Listview에서보기 재사용

그러나 목록에 2 가지 레이아웃이 필요할 때 어떻게이 아이디어를 구현할 수 있습니까? 주문 및 1 개의 레이아웃 목록은 완료 주문에 대한 것이고 다른 레이아웃은 프로세스 주문에 대한 것입니다.

이것은 내 코드에서 사용하는 아이디어의 예제 튜토리얼입니다. 내 경우, 나는 2 열 레이아웃을 것이다 : R.layout.listview_item_product_completeR.layout.listview_item_product_inprocess

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

ViewHolder holder = null; 

if (convertView == null) { 
    holder = new ViewHolder(); 
    if(getItemViewType(position) == COMPLETE_TYPE_INDEX) { 
     convertView = mInflator.inflate(R.layout.listview_item_product_complete, null); 
     holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_complete); 
     holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_complete); 
    } 
    else { // must be INPROCESS_TYPE_INDEX 
     convertView = mInflator.inflate(R.layout.listview_item_product_inprocess, null); 
     holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_inprocess); 
     holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_inprocess); 
    } 
    convertView.setTag(holder); 
} else { 
    holder = (ViewHolder) convertView.getTag(); 
} 
    thisOrder = (Order) myOrders.getOrderList().get(position); 
    // If using different views for each type, use an if statement to test for type, like above 
    holder.mNameTextView.setText(thisOrder.getNameValue()); 
    holder.mImgImageView.setImageResource(thisOrder.getIconValue()); 
    return convertView; 
} 

public static class ViewHolder { 
    public TextView mNameTextView; 
    public ImageView mImgImageView; 
} 
+0

최근에 직접이 문제가 발생했습니다. 나는 listview를 채우기 위해 2 개의 다른 레이아웃을 사용하고 있었고 완전한 무정부 상태가되었습니다. 내 코드를 반복해서 읽었지만 잘못된 레이아웃이 다시 사용되는 이유를 찾지 못했습니다. 결국, 목록 당 * * 레이아웃 하나만 사용하기로 결정했지만 항목 유형에 따라보기를 크게 수정했습니다. 코드에서 항목을 편집 할 수있는 많은 방법이 있습니다. –

답변

83

당신은 어댑터의보기 재활용이 하나 이상의 레이아웃과 방법을 각 행에 대해 두 가지를 구별하는 방법이 있다는 것을 알게해야합니다. 간단하게이 메소드를 오버라이드 (override) :

@Override 
public int getItemViewType(int position) { 
    // Define a way to determine which layout to use, here it's just evens and odds. 
    return position % 2; 
} 

@Override 
public int getViewTypeCount() { 
    return 2; // Count of different layouts 
} 

통합하십시오 getItemViewType()getView() 내에서, 다음과 같이 :

if (convertView == null) { 
    // You can move this line into your constructor, the inflater service won't change. 
    mInflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE); 
    if(getItemViewType(position) == 0) 
     convertView = mInflater.inflate(R.layout.listview_item_product_complete, parent, false); 
    else 
     convertView = mInflater.inflate(R.layout.listview_item_product_inprocess, parent, false); 
    // etc, etc... 

구글 회담에서 시계 안드로이드의 로맹 가이 discuss the view recycler.

+0

좋아, 그래서 홀더 행의 레이아웃에 포함 된 다른보기에 대한 포인터의 복사본 역할을합니다. 필자의 경우 두 레이아웃 모두 동일한 필드 유형을 갖습니다 (형식이 다르게). 그래서 나는 홀더 하나만 필요 하겠지, 맞습니까? 한 레이아웃에 TextView와 ImageView가 있고 다른 TextView에 두 개의 TextView가있는 경우 2 개의 다른 홀더가 필요합니까? – jamis0n

+2

"필자의 경우 두 레이아웃 모두 동일한 필드 유형을 갖기 때문에 (단지 형식이 다름) 홀더가 하나만 필요합니다." 예, 맞습니다. "한 레이아웃에 TextView와 ImageView가 있고 다른 TextView에 2 개의 TextView가 있으면 2 개의 다른 홀더가 필요합니다." 두 개의 다른 ViewHolders를 가질 수도 있고 ViewHolders를 결합 할 수도 있지만 각 레이아웃에 대해 적절한 멤버 만 액세스 할 수 있습니다. 말이 돼? – Sam

+0

너는 남자 야! 그것은 처음으로 작동하지 않습니다! 귀하의 지침을 제외하고 하하 ... 그래서 내 이해를 위해, 홀더는 단지 행 레이아웃의 각보기에 대한 포인터를 잡고있다. ConvertView가 null이거나, 마술처럼'holder = (ViewHolder) convertView.getTag();'호출에서이 포인터들을 집어 들었을 때, 새로 부풀려진 레이아웃들로부터 이것들을 얻는다. 이걸 이해하고 있니? 위의 마지막 코드도 업데이트했습니다 ... 다시 한 번 감사드립니다! – jamis0n

9

솔루션을 직접 설계하지 않아도 getItemViewType() 및 getViewTypeCount()를 재정의 할 수 있습니다. 블로그의 설명에

는 예를 들어 http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

에 대해 다음 블로그 게시물을 참조, 안드로이드의 getView보기의 올바른 유형을 받게됩니다 실제로 보증 않습니다.

+1

이 문제가 발생하지 않았습니다 ...이 블로그입니까 ("Andy"가 작성한 것으로 나타났습니다)? 나는'getDirItem()'이보기 리사이클러가 아니라고 맹세한다. – Sam

+0

그래, 그 나의 blog. 내기 - 얼마 죠? :) 진심으로, 당신의 의견은 내 자신을 의심스럽게 만들었고, 그래서 가서 트리플 코드를 점검하고 디버깅을 더 추가했다. 안드로이드가 때로는 잘못된 시각을 통과하는 경우가 분명합니다. 단서는 getView() 내에서 getItemViewType() 메소드를 사용하여 유형을 결정한다는 것입니다. 그래서 이것이 잘못된 것이라 할지라도 무작위 결과를 반환하지 않는 한 (이 경우가 아니라고 확신하십시오!), 안드로이드는 잘못된 시각을 전달하고 있습니다. – Andy

+0

전에이 문제에 대해 들어 보지 못했습니다 ... 이것을 확인하는 독립적 인 출처가 있습니까? 나는 그것을 직접 보지 못하고 어떤 것도 찾을 수 없다. 모든 코드를 보지 않고 코드에서 실제로 일어나고있는 것을 볼 수는 없습니다. 그러나 처음에는'TYPE_DIR'과'TYPE_PIC'의 값은 무엇입니까? – Sam

관련 문제