[英]Why does my listview reorder when I scroll through it?
當我滾動它時,我的列表視圖重新排序......這非常令人困惑。
這是我正在使用的自定義適配器:
public class LoadExpenseList extends BaseAdapter{
List<Expense> expenses;
Context context;
public LoadExpenseList(Context context, int textViewResourceId,
List<Expense> expenses) {
super();
this.expenses = expenses;
this.context = context;
}
public View getView(final int position, View convertView, ViewGroup parent){
//View v = convertView;
AvailableExpenseView btv;
if (convertView == null) {
btv = new AvailableExpenseView(context, expenses.get(position));
} else {
btv = (AvailableExpenseView) convertView;
}
btv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.i("Expense_Availables", "Item Selected!!");
Intent intent = new Intent(getActivity(), ItemDetailActivity.class);
int id = expenses.get(position).getExpenseItemId();
intent.putExtra("id", id);
startActivity(intent);
}
});
btv.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View arg0) {
// TODO Auto-generated method stub
return false;
}
});
registerForContextMenu(btv);
return btv;
}
@Override
public int getCount() {
return expenses.size();
}
@Override
public Object getItem(int position) {
return expenses.get(position);
}
@Override
public long getItemId(int position) {
return expenses.get(position).getExpenseItemId();
}
}
因為您的視圖( AvailableExpenseView
)是使用項構造的,所以當適配器嘗試通過convertView重用視圖時,您將獲得一個已綁定到另一個項的視圖。
不要使用模型項構造視圖,而是調用convertView.setExpense(expenses.get(position))
。
ListView將嘗試重用視圖以提高性能。 所以會發生的事情是列表中的第一個項目與新創建的視圖一起顯示,稍后當您滾動它時將嘗試重用先前創建的視圖,通過convertView
提供視圖。 注意這些行:
if (convertView == null) {
// You create a view using the proper item
btv = new AvailableExpenseView(context, expenses.get(position));
} else {
// You don't override the item that was previously assigned
// when the view was created
btv = (AvailableExpenseView) convertView;
}
如果convertView為null,則表示您正在創建新視圖,但是您正在使用項目構建視圖。 所以我們假設這是在位置0調用的。使用列表中第一個的開銷創建一個視圖。 稍后,listView想要獲取視圖,讓我們說位置20,並說“ok允許重用我們用於位置0的視圖”,因此它將此視圖作為convertView
傳遞,但此視圖已使用位置0中的項創建而你不要覆蓋它。 因此,您最終使用的視圖中包含第一個項目來表示第20個項目。
要解決這個問題,您可以輕松地執行以下操作:
AvailableExpenseView btv;
if (convertView == null) {
// dont create your view with an item
btv = new AvailableExpenseView(context);
} else {
btv = (AvailableExpenseView) convertView;
}
// Assign the expense wether it is a newly created view or
// a view that is reused
btv.setExpense(expenses.get(position));
當然,您必須編輯AvailableExpenseView
並創建一個setExpense()
方法來填充視圖。
您應該為已回收的AvailableExpenseView
設置Expenses到expenses.get(position),以及為新實例執行此操作。
當實例被回收時,只是在錯誤的線上顯示錯誤(它們在那里實際生成的線而不是你重復使用它們的線)。
更確切地說,您不會為AvailableExpenseView
代碼,但它可能會像您一樣
public class AvailableExpenseView {
private Expense expense = null;
public class AvailableExpenseView( Context context ) {
super( context );
}//cons
/*
Just add this method and use it.
*/
public void setExpense( Expense expense ) {
this.expense = expense;
}//met
}//class
然后,在適配器中執行以下操作:
if (convertView == null) {
btv = new AvailableExpenseView(context);
}
btv = (AvailableExpenseView) convertView;
btv.setExpense( expenses.get( expenses.get(position) ) );
擁有松散構造函數的組件很好。 考慮JVM內部的示例,其中不需要創建按鈕。 然后您可以通過正交方法自定義:屬性的“setters”。 以這種方式設計您的組件,使其易於使用,更多元化。
你的問題在這里:
if (convertView == null) {
btv = new AvailableExpenseView(context, expenses.get(position));
} else {
btv = (AvailableExpenseView) convertView;
}
如果convertView為null,那么您將創建一個新的AvailableExpenseView,其中Expense位於該位置。 這可以。
但是如果convertView不為null,那么您將引用現有的AvailableExpenseView。 之前已將其(在前一種情況下)初始化為與您要在當前位置顯示的費用不同的費用。
您有兩個選擇:在此if塊之后設置btv的費用,以便無論您是創建新的AvailableExpenseView還是回收一個,都會使用正確的費用 -
或:在else塊中,為循環視圖設置正確的Expense對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.