android ListView定位,androidlistview

來源:互聯網
上載者:User

android ListView定位,androidlistview

如果一個ListView太長,有時我們希望ListView在從其他介面返回的時候能夠恢複上次查看的位置,這就涉及到ListView的定位問題:
smoothScrollToPosition需要2.2以上,smoothScrollByOffset需要3.0以上。smoothScrollToPosition可以實現平滑滾動
解決的辦法如下:
// 儲存當前第一個可見的item的索引和位移量
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
// ...
註解:ListView.getChildAt(int position), 這個position指的是在可視的item中的索引,跟cursor裡的位置是大不一樣的。
可以看看ListView.getChildCount()函數得到個數是小於或等於Cursor裡的個數的(不考慮header的話)。
雖然一共可能有20條資料,但是介面只能看到8條,那麼這個ChildCount大約就是8了。
另一方面, FirstVisiblePosition取出的是在總的條數中的索引,再將會消失的header考慮進來,所以就是 FirstVisiblePosition為0時要設為1,大於0時又要設為0。
//根據上次儲存的index和位移量恢複上次的位置
mList.setSelectionFromTop(index, top);
為了說明setSelectionFromTop的參數值的意義,以及與setSelection的區別,下面從源碼上來分析:

看一下setSelectionFromTop()的具體實現,代碼如下:
/**
  * Sets the selected item and positions the selection y pixels from the top edge
  * of the ListView. (If in touch mode, the item will not be selected but it will
  * still be positioned appropriately.)
  *
  * @param position Index (starting at 0) of the data item to be selected.
  * @param y The distance from the top edge of the ListView (plus padding) that the
  *        item will be positioned.
  */
 public void setSelectionFromTop(int position, int y) {
     if (mAdapter == null) {
         return;
     }
     if (!isInTouchMode()) {
         position = lookForSelectablePosition(position, true);
         if (position >= 0) {
             setNextSelectedPositionInt(position);
         }
     } else {
         mResurrectToPosition = position;
     }
     if (position >= 0) {
         mLayoutMode = LAYOUT_SPECIFIC;
         mSpecificTop = mListPadding.top + y;
         if (mNeedSync) {
             mSyncPosition = position;
             mSyncRowId = mAdapter.getItemId(position);
         }
         requestLayout();
     }
 }
 

從上面的代碼可以得知,setSelectionFromTop()的作用是設定ListView選中的位置,同時在Y軸設定一個位移量。
而setSelection()方法,傳入一個index整型數值,就可以讓ListView定位到指定Item的位置。
這兩個方法有什麼區別呢?看一下setSelection()的具體實現,代碼如下:
 
/**
  * Sets the currently selected item. If in touch mode, the item will not be selected
  * but it will still be positioned appropriately. If the specified selection position
  * is less than 0, then the item at position 0 will be selected.
  *
  * @param position Index (starting at 0) of the data item to be selected.
  */
 @Override
 public void setSelection(int position) {
     setSelectionFromTop(position, 0);
 }
原來,setSelection()內部就是調用了setSelectionFromTop(),只不過是Y軸的位移量是0而已。現在應該對setSelection()和setSelectionFromTop()有了更深刻的認識了。

其實還可以使用setSelection也可以定位,只是setSelectionFromTop要比setSelection更精準。
因為通過getFirstVisiblePosition得到的第一個item可能已經有一部分是不可見的了,如果用setSelection無法反映出這不可見的部分。


那麼當Cursor更新時,原先第一條的索引便會發生變化。要想保持住它的位置。步驟如下:

(1)擷取這一條在新Cursor中的位置(posiition)

(2)擷取這一條在更換Cursor後ListView中的位置。

(4)由於ListView的可滾動的屬性,我們需要記錄更換Cursor前可視的第一條item的索引(ListView.getFirstVisiblePosition())

(3)區分FirstVisiblePosition是0和大於0的情況。由於header,也就是圖中的Loading那一條在新資料出來後是會消失的。

(4)當FirstVisiblePosition為0時實際指向的是header,我們要保持位置不變的是header下面第一條(R)的位置。那麼此時要設定FirstVisiblePosition為1

(5)當FirstVisiblePosition大於0時實際指向的就是item,但是我們需要設定FirstVisiblePosition為0。*

(6)我們根據FirstVisiblePosition用ListView.getChildAt(int position)函數擷取對應的item的View,再根據View.getTop()函數擷取到ListView頂部的距離Y。

這樣ListView.setSelectionFromTop(int position, int y)所需的兩個參數 position 和 y就都有了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.