2014-04-02 50 views
2

我有這個奇怪的場景,每次我ListView的第一個項目選擇微調的值,則最後ListView's項目列入微調值與第一項相同。這將只發生當ListView項目的總數是5及以上。我註釋了這些代碼並保留了聲明,並且仍在發生。這是Android中的錯誤嗎?的ListView用離心器:列表視圖的第一個項目會影響其最後一項

澄清:

  • 我的ListView的Scroll Listener是空
  • 我的飛旋的setOnItemSelectedListener被註釋掉。
  • Android SDK中工具版本22.6.2是
  • 的Android SDK平臺的工具是19.0.1

    enter image description here

這裏的適配器代碼:

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

    Viewholder v = new Viewholder(); 
    v.rowView = convertView; 
    LayoutInflater inflater = (LayoutInflater) context 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    if (v.rowView == null) { 
     v.rowView = inflater.inflate(R.layout.inner_base_header_cutom, parent, false); 
     v.spinner = (Spinner) v.rowView.findViewById(R.id.spinner1); 
     v.rowView.setTag(v); 
    } else { 
     v = (Viewholder) v.rowView.getTag(); 
    } 

    return v.rowView; 
} 

ViewHolder:

class Viewholder{ 
    View rowView; 
    TextView itemPID; 
    TextView itemPrice; 
    TextView itemItemId; 
    Spinner spinner; 
    TextView subtotal; 
} 

XML:

<Spinner 
    android:id="@+id/spinner1" 
    android:layout_width="100dip" 
    android:layout_height="wrap_content" 
    android:layout_margin="20dip" 
    android:entries="@array/quanitiy" 
    android:layout_alignTop="@+id/itemPrice" 
    android:layout_toRightOf="@+id/imageDisplay" /> 

陣:

<string-array name="quanitiy"> 
     <item>Quantity</item> 
     <item>1</item> 
     <item>2</item> 
     <item>3</item> 
     <item>4</item> 
     <item>5</item> 
     <item>6</item> 
     <item>7</item> 
     <item>8</item> 
     <item>9</item> 
     <item>10</item> 
    </string-array> 

UPDATE 我註釋掉的代碼OnItemClickListner。我更新了上面的代碼,仍然存在問題。唯一剩下的就是聲明。

場景: 如果我在飛旋的第一項選擇1ListView的[索引0],ListView的微調的最後一個項目也1變得沒有互動。當列表視圖的項目一直到最後一部分時,我才發現它們都是相同的。我註釋了這些代碼並保留了聲明。

+0

請縮進代碼。然後我會看看它;)如果你使用Eclipse,Ctrl + Maj + F是你的朋友! – Joffrey

+0

好多了:D – Joffrey

+0

謝謝@SilentKiller。 – rahstame

回答

4

好了,現在我明白了。感謝您的澄清。您的問題來自正在回收的視圖。你應該看看this post以更好地理解回收。

簡短的回答

基本上,當您使用getView()convertView,要重複使用是不再可見項目的看法。這就是爲什麼它的領域(包括微調,價格的textview)已被設置爲某些東西,你應該自己設置它們在getView()。賦予這些文本框和微調框的值應取決於指定的position處的項目。

詳細的答案

這裏就是回收做(從前面提到的後拍攝的照片):

recycling process

你的問題

這裏當您滾動顯示一個新的項目(讓我們說第8項,就像圖片一樣),用於顯示它的視圖與第一個項目(項目1)的視圖相同。因此,當您在第一個項目的微調器上選擇了一些內容,然後向下滾動時,您會看到最後一項中的更改,因爲您的getView不會更改用於項目1的視圖的值(但它應該更新它們!)。

注意:您案例中第一項和最後一項的對應關係完全是偶然的。通常情況下,視圖可以重複使用2個項目,這些項目大約以一個屏幕高度中的項目數量分隔,如圖所示。

內聯的解釋在你的代碼getView

Viewholder v = new Viewholder(); // why create a new one, while you might reuse the former one? 

// here rowView becomes the same as the former item's view, with all the former values 
v.rowView = convertView; 

// you don't need this here but only in the case rowView is null, should be in your 'if' 
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

if (v.rowView == null) { 
    v.rowView = inflater.inflate(R.layout.inner_base_header_cutom, parent,false); 
    v.spinner = (Spinner) v.rowView.findViewById(R.id.spinner1); 
    v.rowView.setTag(v); 
    // here you inflated a new view (nothing reused) 
    // but you didn't initialize anything 
} else { 
    v = (Viewholder) v.rowView.getTag(); 
    // here you're reusing the former View and ViewHolder 
    // and you don't change the values 
} 

解決方案

你不應該讓項目的行爲,因爲他們請,但你應該告訴他們,以顯示你的時候初始化getView()中的項目視圖內容。對於上面的圖片,這意味着您需要將原來是第1項的內容更改爲第8項

您應該保持適配器中每個項目的狀態。你可能有一個支持列表或其他東西來顯示ListView中的不同元素,具體取決於position,對吧? 然後,您應該使用類似的列表(或相同)來存儲在微調器中選擇的值,價格等文本字段顯示的值。這些應該可能對應於當前列表中項目的字段,所以你可能已經有了一些地方來存儲它們。

在另一方面,當你重用getView()convertView,確保您在position初始化(在這個項目視圖和文本字段,一切)微調與該項目的正確值。

解決方案代碼(模板)爲getView

Viewholder v; 

if (convertView == null) { 
    // create a new holder for the new item view 
    v = new Viewholder(); 
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    v.rowView = inflater.inflate(R.layout.inner_base_header_cutom, parent,false); 
    v.rowView.setTag(v); 

    // populate the new holder's fields 
    v.spinner = (Spinner) v.rowView.findViewById(R.id.spinner1); 
    v.itemPID = (TextView) v.rowView.findViewById(...); // put the right ID here 
    v.itemPrice = (TextView) v.rowView.findViewById(...); // put the right ID here 
    v.itemItemId = (TextView) v.rowView.findViewById(...); // put the right ID here 
    v.subtotal = (TextView) v.rowView.findViewById(...); // put the right ID here 
} else { 
    v = (Viewholder) convertView.getTag(); 
    // the views of v are already populated here (reused)  
} 

/* 
* Reused or not, the item view needs to be initialized here. 
* Initialize all views contained in v with values that are 
* meaningful for the item at 'position'. 
*/ 

// for instance: 
MyItemClass theItemAtPosition = myBackingList.get(position); 
v.subtotal.setText(String.valueOf(theItemAtPosition.getSubtotal())); 
v.spinner.setSelection(theItemAtPosition.getQuantity()); 

// to be continued, you get the idea ;) 
+0

謝謝你的解釋,我需要時間來研究你的答案。你能提出一個更好的代碼嗎?再次感謝。 – rahstame

+1

我編輯了我的答案,向您展示瞭解決方案的一些代碼。但我不能做更多不知道你的列表如何(我的意思是列表內容,ListView的支持列表) – Joffrey

+1

現在看起來更好,你應該能夠徹底地理解你的問題;) – Joffrey

相關問題