簡體   English   中英

內含Spinner的ListView:listview的第一項影響其最后一項

[英]ListView with Spinner Inside: 1st Item of the listview affects its last item

我有這種奇怪的情況,每次我ListView的1st Item中的微調器中選擇一個值時, 其Spinner值最后一個ListView's項與第一個項相同 當ListView項的總數等於或大於5時, 才會發生這種情況 我注釋掉了代碼,只保留了聲明,並且這種情況仍在發生。 這是Android中的錯誤嗎?

澄清:

  • 我的ListView的Scroll Listener為空
  • 我的微調器的setOnItemSelectedListener已被注釋掉。
  • Android SDK Tool版本為22.6.2
  • Android SDK平台工具為19.0.1

    在此處輸入圖片說明

這是適配器代碼:

@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>

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

場景:如果我在ListView的微調器的第一項[index 0]上選擇1 ,則ListView的微調器的最后一項也會獲得1而沒有交互。 當將listview的項目放到最后部分時,我發現它們都是相同的。 我注釋掉了代碼,只保留了聲明。

好的,現在我明白了。 感謝您的澄清。 您的問題來自於視圖被回收。 您應該看一下這篇文章,以更好地了解回收。

簡短的答案

基本上,當在getView()使用convertView時,將重用不再可見的項目的視圖。 這就是為什么它的字段(包括微調框,價格的文本視圖...)已經設置為某些內容的原因,因此您應該在getView()自己設置它們。 提供這些文本字段和微調框的值應取決於指定position的項目。

詳細答案

這是回收的作用(圖片來自前面提到的帖子):

回收過程

你的問題

在這里,當您滾動以顯示一個新項目(例如圖片中的第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

您應該將每個項目的狀態保留在適配器中。 您可能有一個后備列表或一些東西,以根據positionListView顯示不同的元素,對嗎? 然后,您應該使用類似的列表(或相同的列表)來存儲微調器中選擇的值,價格的文本字段中顯示的值等。無論如何,這些值可能應該與當前列表中項目的字段相對應,因此您可能已經有一些地方可以存儲它們了。

另一方面,在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 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM