ScrollBar作为一个基础功能被实现在View中,子类需要实现computeXXXScrollRange、computeXXXScrollExtent和computeXXXScrollOffset这三个方法,其中:
1、computeXXXScrollRange,计算滚动条的滚动范围
2、computeXXXScrollExtent,计算滑块显示的大小
3、computeXXXScrollOffset,计算滚动的偏移量,也就是当前滚动的位置
上面这三个方法返回的值都是相对值,也就是计算的时候采用一个统一的度量,具体视图上的显示在View的onDrawScrollbar()方法中已经实现。
有了这三个方法之后,还需要调用在滚动的过程中调用awakenScrollbars(),因为Scrollbar在停止滚动后会自动隐藏,所以就需要在滚动的时候不断唤起scrollbar让它显示出来,也就是这个方法。
HorizontalListView通过监听滚动手势来不断requestLayout,重新布局列表的显示来达到滚动的效果,所以awakenScrollbars这个方法就添加在onLayout中。
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (mAdapter == null) { return; } // Force the OS to redraw this view if (!awakenScrollBars()) { postInvalidate(); } ... }
@Override protected int computeHorizontalScrollRange() { int count = mAdapter.getCount(); return Math.max(count * 100, 0); } @Override protected int computeHorizontalScrollExtent() { int count = getChildCount(); if (count > 0) { int extent = count * 100; View view = getChildAt(0); final int left = view.getLeft(); int width = view.getWidth(); if (width > 0) { extent += (left * 100) / width; } view = getChildAt(count - 1); final int right = view.getRight(); width = view.getWidth(); if (width > 0) { extent -= ((right - getWidth()) * 100) / width; } return extent; } return 0; } @Override protected int computeHorizontalScrollOffset() { final int firstPosition = mLeftViewAdapterIndex; final int childCount = getChildCount(); if (firstPosition >= 0 && childCount > 0) { final View view = getChildAt(0); final int left = view.getLeft(); int width = view.getWidth(); if (width > 0) { int result = Math.max(firstPosition * 100 - (left * 100) / width, 0); return result; } } return 0; }