Android入門 在ListView中如何進行精確的位置設定

來源:互聯網
上載者:User

在android的開發中,經常會遇到需要主動去設定某條ListItem的位置的需求。設定位置的函數有

ListView.setSelection(int position)

ListView.setSelectionFromTop(int position, int y);

其中

position指的是指定的item的在ListView中的索引,注意如果有Header存在的情況下,索引是從Header就開始算的。

y指的是到ListView可見範圍內最上邊邊緣的距離。

函數有了,現在就是根據自身需求來進行設定。


這次遇到的需求,ListView要求是從下往上展示的,並且當Cursor更新時,要保持住原先的最上方的item(不包括header)的位置不變,然後新的曆史資料在原先那條item上方繼續向上展示。


ListView從下往上展示,也就是

[java] 
android:stackFromBottom="true" 
但是發現這一屬性的設定不會影響索引的排序次序,也就是item的索引都是從上往下遞增的,不會變成從下往上遞增。索引為0的item,都是在ListView的最上方的item(或header).
那麼當Cursor更新時,原先第一條的索引便會發生變化。要想保持住它(圖中的 R)的位置。步驟如下:

(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就都有了。

*註解:ListView.getChildAt(int position), 這個position指的是在可視的item中的索引,跟cursor裡的位置是大不一樣的。可以看看ListView.getChildCount()函數得到個數是小於或等於Cursor裡的個數的(不考慮header的話)。雖然一共可能有20條資料,但是介面只能看到8條,那麼這個ChildCount大約就是8了。另一方面, FirstVisiblePosition取出的是在總的條數中的索引,再將會消失的header考慮進來,所以就是 FirstVisiblePosition為0時要設為1,大於0時又要設為0。

下面上代碼:

調用的代碼:

[java] 
int headerCount = mListContainer.getListView().getHeaderViewsCount(); 
int firstVisiblePos = mListContainer.getListView().getFirstVisiblePosition(); 
int newCursorPosition = getPositionInNewCursor(cursor.getCount(), firstVisiblePos); 
int offsetY = getOffsetY(cursor, firstVisiblePos, newCursorPosition); 
 
mAdapter.changeCursor(cursor); 
 
mUpRefreshLayout.setVisibility(View.GONE); 
       
mListContainer.getListView().setSelectionFromTop(newCursorPosition + headerCount, offsetY); 
getPositionInNewCursor函數:
[java] 
private int getPositionInNewCursor(int newCursorCount, int firstVisiblePos){ 
    if(firstVisiblePos == 0){ 
        firstVisiblePos += 1; 
    } 
 
    int headerCount = mListContainer.getListView().getHeaderViewsCount(); 
    int newCursorPos = newCursorCount - mAdapter.getCount() + firstVisiblePos - headerCount; 
     
    return newCursorPos; 

getOffsetY函數:
[java] 
private int getOffsetY(Cursor cursor, int firstVisiblePos, int newCursorPosition){ 
        int y; 
         
        View firstVisibleItem = null; 
        if(firstVisiblePos == 0){ 
            firstVisibleItem = mListContainer.getListView().getChildAt(1); 
        }else{ 
            firstVisibleItem = mListContainer.getListView().getChildAt(0); 
        } 
        y = firstVisibleItem.getTop(); 
 
        View timeView = firstVisibleItem.findViewById(R.id.time_text_view); 
        if(timeView != null && timeView.getVisibility() == View.VISIBLE){ 
 
            Cursor curItem = (Cursor)mAdapter.getItem(newCursorPosition); 
            Cursor preItem = (Cursor)mAdapter.getItem(newCursorPosition - 1); 
            if(curItem != null || preItem != null){ 
                long curTimeStamp = curItem.getLong(MessagesProjection.JEDI_CREATE_DATE_INDX); 
                long preTimeStamp = preItem.getLong(MessagesProjection.JEDI_CREATE_DATE_INDX); 
                 
                if(Math.abs(curTimeStamp - preTimeStamp) <= SHOW_TIME_STAMP_TEN_MINS){ 
                    LayoutParams param = (LinearLayout.LayoutParams)mTimeView.getLayoutParams(); 
                    y += mTimeView.getHeight() + param.topMargin + param.bottomMargin; 
                } 
            } 
        } 
         
        return y; 
    } 

getOffsetY中有一段計算圖中TimeStamp的高度的代碼,不關心的可以自己跳過一下。因為查詢出曆史資料後可能會造成原先有TimeStamp的那一條在重新整理後不再顯示TimeStamp(與上一條合并到一個時間段了),所以要把它的高度也計算進去。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.