滑动相关的很多代码在View里面已经有了,如果自定义一个类似ScrollView的布局,不考虑手势滑动,直接通过代码scrollTo或scrollBy来设置滑到的区域,只需要覆写几个成员方法即可,以下是实现此功能的一个简单例子:
//一个简单的垂直ScrollView,不支持手势滑动,只能通过代码调用scrollTo或scrollBy来设置滚动位置,并且能显示滚动条
public class SimpleScrollView extends FrameLayout {
public SimpleScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);//必须调用这句,否则滚动条无法显示出来,另外布局文件中必须有android:scrollbars属性
}
/*
* 计算垂直滚动条区域,如果返回值大于此ScrollView显示的垂直区域(去掉顶部和底部边距),才能显示滚动条
* 如果要实现水平ScrollView,则仿照此方法中的代码覆写computeHorizontalScrollRange
*/
@Override
protected int computeVerticalScrollRange() {
final int count = getChildCount();
final int contentHeight = getHeight() - getPaddingBottom() - getPaddingTop();
if (count == 0) {
return contentHeight;
}
int scrollRange = getChildAt(0).getBottom();
final int scrollY = getScrollY();
final int overscrollBottom = Math.max(0, scrollRange - contentHeight);
if (scrollY < 0) {
scrollRange -= scrollY;
} else if (scrollY > overscrollBottom) {
scrollRange += scrollY - overscrollBottom;
}
return scrollRange;
}
//计算子View的布局大小,主要是让子View的高度能适应其内容
@Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
/*
* 这里的MeasureSpec.UNSPECIFIED参数能够让子View的高度超过屏幕的显示高度区域,
* 如果是实现一个水平的ScrollView,则可仿照此方式来设置上一句代码中计算子View宽度的代码
*/
final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}