2011-04-25 6 views
0

ListView에 대한 사용자 지정 어댑터를 사용하는 매우 간단한 응용 프로그램을 개발했습니다.ListView의 각 행에서 다른 "가시성"값

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical"> 
    <TextView android:id="@+id/text1" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:textAppearance="?android:attr/textAppearanceMedium" /> 
    <TextView android:id="@+id/text2" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:textAppearance="?android:attr/textAppearanceSmall" 
     android:visibility="gone" /> 
</LinearLayout> 

제 텍스트 뷰의 이름은 "텍스트 1", 두 번째 "텍스트 2"

각 행은 두 TextViews있다. 보시다시피, text2가 숨겨져 있습니다 (visibility = "gone").

또한,이 목록은 단지 글고 위젯을 포함하는 헤더를 가지고

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 
    <EditText android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 
</LinearLayout> 

각 행은 두 속성 (텍스트 및 텍스트 2)가 "품목"이라는 매우 간단한 객체로 표시하고, 해당되는 getters/setters. 또한, 단지 객체가 텍스트 2 속성 값의 길이가 있는지 확인하는 "hasText2"방법이있다> 0 :

public class Item { 
    private String text1; 
    private String text2; 

    public String getText1() { 
     return text1; 
    } 
    public void setText1(String text1) { 
     this.text1 = text1; 
    } 
    public boolean hasText2() { 
     return text2.length() > 0; 
    } 
    public String getText2() { 
     return text2; 
    } 
    public void setText2(String text2) { 
     this.text2 = text2; 
    } 
} 

좋아, 내 주요 응용 프로그램 파일에 단 2 항목 목록을 초기화 할 수 있습니다 :

Item item1 = new Item(); 
item1.setText1("Item 1"); 
item1.setText2("optional 1"); 
Item item2 = new Item(); 
item2.setText1("Item 2"); 
item2.setText2(""); 

getListView().addHeaderView(getLayoutInflater().inflate(R.layout.list_header, null), false, false); 

m_items = new ArrayList<Item>(); 
m_adapter = new CustomListAdapter(this, R.layout.list_row, m_items); 
setListAdapter(m_adapter); 

m_items.add(item1); 
m_items.add(item2); 
m_adapter.notifyDataSetChanged(); 

이 내 사용자 정의 어댑터의 getView 방법 (즉 ArrayAdapter와 확장)되어 는 텍스트 2 위젯을 표시하는 항목 객체가

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = vi.inflate(R.layout.list_row, null); 
    } 

    // get the two text widgets of this row layout 
    TextView text1 = (TextView) convertView.findViewById(R.id.text1); 
    TextView text2 = (TextView) convertView.findViewById(R.id.text2); 

    // get the Item object of this row 
    Item list_item = items.get(position); 

    // we set the text1 property of this Item to the text1 widget 
    text1.setText(list_item.getText1()); 

    // if this Item has a text2 (value length > 0), then set it to the text2 widget and make it visible 
    if (list_item.hasText2()) { 
     text2.setText(list_item.getText2()); 
     text2.setVisibility(0); 
    } 

    return convertView; 
} 

그럼, 내가 원하는 것은 경우에만 그것은 (값의 길이> 0)을 정의했다.

그리고이 앱을 실행 한 후 결과입니다

enter image description here 좋은

, 그것이 내가 예상대로 작동합니다! :)

그러나 목록 헤더의 EditText를 탭하면 어떻게됩니까? (그래서 나는 목록을 업데이트하기 위해 강제로) :

enter image description here

은 무엇 여기 일이? 불가능합니다. 두 번째 행에는 text2가 정의되어 있지 않으며 Android는 첫 번째 행에서 text2를 가져 왔습니다. 왜??

내가 상상할 수있는 유일한 이유는 다른 가시성을 가진 행을 사용할 수 없다는 것입니다. 그렇다면 안드로이드가 방금 앱을 실행할 때 왜 그렇게 했습니까? 키보드가 나타나는 경우에만 실패하는 것 같습니다 (목록 업데이트).

+0

, 당신은 getViewTypeCount''정의한 뷰의 수와보기 유형 : 다음과 같은 수정은 아마 문제를 해결하는 것이 경우

'getItemViewType' – binnyb

+0

그래서 두 개의 행 레이아웃을 정의해야합니까? 몇 가지 지침을 어디에서 찾을 수 있습니까? 목록이 업데이트 될 때만 이것이 왜 발생하는지 이해하지 못합니다 (첫 번째 스크린 샷). –

답변

2

위의 질문에 대한 설명과 정확히 같은 이유로 문제가 있습니다. 뷰가 재활용 중이므로 if (list_item.hasText2()) { 절에서 수행 된 사용자 정의가 해당 뷰에 영구적으로 설정됩니다. 그 조항이 사실이 아닐 것이라는 관점으로 재활용 될 때조차도. 이 getView``재활용 전망과 관련이있다

if (list_item.hasText2()) { 
    text2.setText(list_item.getText2()); 
    text2.setVisibility(View.VISIBLE); 
} else { 
    text2.setVisibility(View.GONE); 
} 
+0

안녕하세요 짐, 도움을 주셔서 감사합니다. 그래, 문제가 해결되었지만 "if"의 맞춤 설정이 영구적으로 설정된 이유를 이해할 수 없습니다. 이것에 대한 문서가 있습니까? 나는 어떤 것을 찾을 수 없으며 이것이 정확히 어떻게 작동 하는지를 알면 행복 할 것이다. :) –

+0

'return convertView;'를 실행하면 시스템은 똑같은 객체를 다시 만들 것이다. 그러나 원래 뷰가 화면에서 사라지면 public 뷰 getView (int position, View convertView, ViewGroup parent) {'의 두 번째 매개 변수로 * 다른 * 위치에 대해. –

+0

@JimBlackler 효율적인 재활용 방법을 고수하기를 원한다면이 목표를 달성하는 유일한 방법일까요? 내 행의 레이아웃을 변경하는 조건이 많습니다. 즉, _if-block_의 모든 변경은 행이 재사용되는 경우 값을 재설정하기 위해 해당 _else-block_을 필요로합니다. 이것은 매우 장황 해지고 _getView() _ 메소드는 다소 혼란 스럽습니다. – jenzz

관련 문제