ScrollView可滑动的原理

滑动相关的很多代码在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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值