2010-12-13 55 views
16

我使用ListView創建圖片列表,並且照片的大小適合屏幕上的2至3張照片。列表視圖管理單元

我遇到的問題是,當用戶停止滾動時,可見列表的第一項會捕捉到屏幕的頂部,例如,如果滾動結束並且小部分首先顯示的圖片,我們向下滾動列表以使圖片始終完全顯示,如果主要顯示圖片,我們向上滾動列表以便下一張圖片完全可見。

有沒有一種方法來實現這個在Android與列表視圖?

回答

26

我已經找到一種方法來做到這一點只是聽時,通過實施ListView.OnScrollListener

@Override 
public void onScrollStateChanged(AbsListView view, int scrollState) { 
    switch (scrollState) { 
    case OnScrollListener.SCROLL_STATE_IDLE: 
     if (scrolling){ 
      // get first visible item 
      View itemView = view.getChildAt(0); 
      int top = Math.abs(itemView.getTop()); // top is a negative value 
      int bottom = Math.abs(itemView.getBottom()); 
      if (top >= bottom){ 
       ((ListView)view).setSelectionFromTop(view.getFirstVisiblePosition()+1, 0); 
      } else { 
       ((ListView)view).setSelectionFromTop(view.getFirstVisiblePosition(), 0); 
      } 
     } 
     scrolling = false; 
     break; 
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: 
    case OnScrollListener.SCROLL_STATE_FLING: 
     Log.i("TEST", "SCROLLING"); 
     scrolling = true; 
     break; 
    } 
} 

的變化結束滾動也不是那麼順暢,但它的工作原理進行滾動和改變位置。

+0

如果你想讓它平滑嘗試使用(((ListView)視圖)。smoothScrollToPosition(POS); – stealthcopter 2012-11-23 13:03:50

+2

這樣做的兩個問題:1)smoothScrollToPosition會導致上述邏輯檢測到另一個滾動並進入一個緊張的循環 - 您可以通過刪除SCROLL_STATE_FLING的情況來避免這種情況,但我不確定這是否是一個很好的解決方法。 2)smoothScrollToPosition不能正確對齊,至少與我的列表。它將指定項目的頂部滾動到列表視圖頂部以上15像素,而不是像setSelection/setSelectionFromTop那樣正確對齊。 – benkc 2013-01-02 21:22:26

+0

任何順利的解決方案? – benkol 2014-02-18 11:11:21

0

除了嘗試代碼上面的一件事情,你應該確保你的listView有一個高度,可以適合你想要顯示的項目的確切數量。 例如 如果您希望在捕捉效果後顯示4個項目,並且您的行高(在其佈局中定義)應該爲列表總高度的1/4。

2

使用@nininho的溶液,

onScrollStateChanged當狀態變爲SCROLL_STATE_IDLE,記住捕捉並提高標誌的位置:

snapTo = view.getFirstVisiblePosition(); 
shouldSnap = true; 

然後,重寫computeScroll()方法:

@Override 
public void computeScroll() { 
    super.computeScroll(); 
    if(shouldSnap){ 
     this.smoothScrollToPositionFromTop(snapTo, 0); 
     shouldSnap = false; 
    } 
} 
5

利用@ nininho解決方案中的一些想法,我得到了我的列表視圖,以平滑的scr而不是突然地去做它。有一點需要注意的是,我只是在帶有文本的基本ListView的Moto X上測試了這個解決方案,但它在設備上運行得非常好。不過,我對這個解決方案充滿信心,並鼓勵您提供反饋意見。

listview.setOnScrollListener(new OnScrollListener() { 
     @Override 
     public void onScrollStateChanged(AbsListView view, int scrollState) { 
      // TODO Auto-generated method stub 
      if (scrollState == SCROLL_STATE_IDLE) { 
       View itemView = view.getChildAt(0); 
       int top = Math.abs(itemView.getTop()); 
       int bottom = Math.abs(itemView.getBottom()); 
       int scrollBy = top >= bottom ? bottom : -top; 
       if (scrollBy == 0) { 
        return; 
       } 
       smoothScrollDeferred(scrollBy, (ListView)view); 
      } 
     } 

     private void smoothScrollDeferred(final int scrollByF, 
       final ListView viewF) { 
      final Handler h = new Handler(); 
      h.post(new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 
        viewF.smoothScrollBy(scrollByF, 200); 
       } 
      }); 
     } 

     @Override 
     public void onScroll(AbsListView view, int firstVisibleItem, 
       int visibleItemCount, int totalItemCount) { 
      // TODO Auto-generated method stub 

     } 
    }); 

我之所以推遲平滑滾動是因爲在我的測試,直接調用該州smoothScrollBy方法改變了回調實際上問題滾動。另外,我沒有預見到一個經過充分測試,強大的解決方案,持有非常多的狀態,在我的解決方案中,我根本沒有任何狀態。此解決方案尚未在Google Play商店中推出,但應作爲一個很好的起點。

+0

當'top> = bottom'時,'scrollBy'等於(** N:在GridView中爲col cols,N爲1爲ListView)'view.getChildAt(view.getFirstVisiblePosition()+ N).getY()'。 – samosaris 2017-08-30 19:18:20

0

注意,smoothScrollBy()調用後,getFirstVisiblePosition()可能指向上面的最上面的列表視圖列表項。當view.getChildAt(0).getBottom() == 0時尤其如此。我不得不打電話view.setSelection(view.getFirstVisiblePosition() + 1)補救這種奇怪的行爲。