为Android HorizontalListView添加Scrollbar

最近由于项目需要,要实现一个横向滚动的列表,打算直接用HorizontalScrollView,但是因为没有视图复用,列表项多了之后会占用较多内存,排除;再想到用Gallery,但Gallery有一个自动定位到中央的动画效果,要去除这个效果的工作比较复杂。最后搜了一下找到了这个 Android-HorizontalListView,实现了ListView的大部分功能,只是不支持Header、Footer和ScrollBar,项目要求提供Scroolbar的显示,所以就在上面动手吧,添加横向的Scrollbar。

ScrollBar作为一个基础功能被实现在View中,子类需要实现computeXXXScrollRange、computeXXXScrollExtent和computeXXXScrollOffset这三个方法,其中:

1、computeXXXScrollRange,计算滚动条的滚动范围

2、computeXXXScrollExtent,计算滑块显示的大小

3、computeXXXScrollOffset,计算滚动的偏移量,也就是当前滚动的位置

上面这三个方法返回的值都是相对值,也就是计算的时候采用一个统一的度量,具体视图上的显示在View的onDrawScrollbar()方法中已经实现。

有了这三个方法之后,还需要调用在滚动的过程中调用awakenScrollbars(),因为Scrollbar在停止滚动后会自动隐藏,所以就需要在滚动的时候不断唤起scrollbar让它显示出来,也就是这个方法。

HorizontalListView通过监听滚动手势来不断requestLayout,重新布局列表的显示来达到滚动的效果,所以awakenScrollbars这个方法就添加在onLayout中。

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. protected void onLayout(boolean changed, int left, int top, int right,  
  2.             int bottom) {  
  3.         super.onLayout(changed, left, top, right, bottom);  
  4.   
  5.         if (mAdapter == null) {  
  6.             return;  
  7.         }  
  8.   
  9.         // Force the OS to redraw this view  
  10.         if (!awakenScrollBars()) {  
  11.             postInvalidate();  
  12.         }  
  13.   
  14.         ...  
  15. }  

下面添加scrollbar相关的计算

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2.     protected int computeHorizontalScrollRange() {  
  3.         int count = mAdapter.getCount();  
  4.         return Math.max(count * 1000);  
  5.     }  
  6.   
  7.     @Override  
  8.     protected int computeHorizontalScrollExtent() {  
  9.         int count = getChildCount();  
  10.         if (count > 0) {  
  11.             int extent = count * 100;  
  12.   
  13.             View view = getChildAt(0);  
  14.             final int left = view.getLeft();  
  15.             int width = view.getWidth();  
  16.             if (width > 0) {  
  17.                 extent += (left * 100) / width;  
  18.             }  
  19.   
  20.             view = getChildAt(count - 1);  
  21.             final int right = view.getRight();  
  22.             width = view.getWidth();  
  23.             if (width > 0) {  
  24.                 extent -= ((right - getWidth()) * 100) / width;  
  25.             }  
  26.   
  27.             return extent;  
  28.   
  29.         }  
  30.         return 0;  
  31.     }  
  32.   
  33.     @Override  
  34.     protected int computeHorizontalScrollOffset() {  
  35.         final int firstPosition = mLeftViewAdapterIndex;  
  36.         final int childCount = getChildCount();  
  37.         if (firstPosition >= 0 && childCount > 0) {  
  38.             final View view = getChildAt(0);  
  39.             final int left = view.getLeft();  
  40.             int width = view.getWidth();  
  41.             if (width > 0) {  
  42.                 int result = Math.max(firstPosition * 100 - (left * 100) / width, 0);  
  43.                 return result;  
  44.             }  
  45.         }  
  46.         return 0;  
  47.     }  

这里参考了AbsListView中的实现,上面的计算过程比较容易理解,×100是为了保持两位小数的精度。range的值就是总的列表项个数(mAdapter.getCount());滑块的大小extent是当前显示的个数,然后去除左右边界超出的部分来提高精度;offset是显示的第一个列表的索引值。也就是说上面采用了“个数”为度量单位进行计算。




FROm:http://blog.csdn.net/xu_fu/article/details/41792657





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值