2010-12-13 56 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)补救这种奇怪的行为。