簡體   English   中英

當我滾動瀏覽時,為什么我的listview會重新排序?

[英]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.

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