[英]ListView with Spinner Inside: 1st Item of the listview affects its last item
我有這種奇怪的情況,每次我從ListView
的1st Item中的微調器中選擇一個值時, 其Spinner值的最后一個ListView's
項與第一個項相同 。 僅當ListView項的總數等於或大於5時, 才會發生這種情況 。 我注釋掉了代碼,只保留了聲明,並且這種情況仍在發生。 這是Android中的錯誤嗎?
澄清:
Scroll Listener
為空 setOnItemSelectedListener
已被注釋掉。 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 。
您應該將每個項目的狀態保留在適配器中。 您可能有一個后備列表或一些東西,以根據position
在ListView
顯示不同的元素,對嗎? 然后,您應該使用類似的列表(或相同的列表)來存儲微調器中選擇的值,價格的文本字段中顯示的值等。無論如何,這些值可能應該與當前列表中項目的字段相對應,因此您可能已經有一些地方可以存儲它們了。
另一方面,在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.