一对一直播源码绘制滚动条

protected final void onDrawScrollBars(Canvas canvas) {
    // scrollbars are drawn only when the animation is running
    /**
     * onDrawScrollBarQ函数内部的执行流程如下。
     * 1) 判断该View对象内部是否存在ScrollabilityCache对象,即变量mScrollCache是否为空。对应
     * 用程序而言,当需要视图显示滚动条时,可以在XM L文件中使用androidiscrollbars属性为视图指定滚
     * 动条,属性值可以是vertical、 horzontal、 none,从而在View的构造函数中将会调用initializeScrollbars()
     * 创建一个ScrollablilityCache对象。如果View对象不是从XML文件中产生,而是通过程序动态产生,
     * 则可以调用View类 的 setScrollbarFaddingEnable(boolean)函数设置滚动条是否“ 自动隐藏(fadding)”,该
     * 函数内部则会调用initializeScrollbars()初 始 化 ScrollabilityCache对象。什么是“自动隐藏”?Android
     * 中的滚动条和PC上的滚动条有所不同,对 于 PC上的滚动条而言,在一般情况下滚动条会一直存在,
     * 在默认情况下滚动条并不显示,只有当用户做滚动操作时才会显示,滚动完毕后,滚动条就会自动藏起
     * 来,这就叫自动隐藏。应用程序可以调用setScmllbarFaddingEnable()设置是否自动隐藏,在默认情况下
     * 是自动隐。
     */
    final ScrollabilityCache cache = mScrollCache;
    if (cache != null) {
        /**
         * 2)如 果 cache存在,则继续判断cache的 状 态 (state)。 ScrollablilityCache内部有两种状态,分别
         * 为 ON和 OFF,ON意味着滚动条处于显示状态,OFF意味着滚动条处于隐藏状态。因此,本步骤判断
         * 如果是OFF状态的话,就直接返回。
         * 那么,什么时候是ON,什么时候是OFF呢?如果滚动条是自动隐藏,那么,在
         * setScrollbarFaddingEnable()函数中会将该cache的状态置为OFF,否则置为ON。如果是自动隐藏,那么
         * 当应用程序调用scrollBy()函数时,该函数内部会间接调用awakenScrollBars(),该函数中会把cache的
         * 状 态 “暂时置” 为 ON。为什么这里是暂时呢?因为该函数将cache状态置为ON后,紧接着会发送一
         * 个异步延迟消息,在指定的延迟时间后,消息的处理函数又会重新将cache的状态置为OFF,从而使得
         * 在下次绘制滚动条时会在本步骤中直接返回,这也就是“ 自动隐藏” 的具体过程。
         * awakenScrollBars()函数的类型是protected,意味着该函数只能被重载,而不能被应用程序直接调用,
         * 应用程序一般只能调用scrollBy()函数。而对于自定义View而言,比如ListView,其内部实际上并没有
         * 滚动值,所以也就不能调用 scrollBy()函数,而它实现滚动条自动隐藏的效果正是借助于
         * awakenScrollBars()函数。
         */
        int state = cache.state;
        
        if (state == ScrollabilityCache.OFF) {
            return;
        }
        
        boolean invalidate = false;
        /**
         * 3 判 断 cache的状态是否为FADING。FADDING的本质上依然是ON,只 是 它 “正在隐藏”,
         * 所 谓 “正在隐藏” 的效果一般就是滚动条“逐渐消失”,其实现方法是逐渐减少滚动条的阿尔法通道值。
         * 如果不是FADDING,则将阿尔法值设为Oxff,也就是完全不透明。
         */
        if (state == ScrollabilityCache.FADING) {
            // We're fading -- get our fade interpolation
            if (cache.interpolatorValues == null) {
                cache.interpolatorValues = new float[1];
            }
            
            float[] values = cache.interpolatorValues;
            
            // Stops the animation if we're done
            if (cache.scrollBarInterpolator.timeToValues(values) ==
                    Interpolator.Result.FREEZE_END) {
                cache.state = ScrollabilityCache.OFF;
            } else {
                cache.scrollBar.setAlpha(Math.round(values[0]));
            }
            
            // This will make the scroll bars inval themselves after 
            // drawing. We only want this when we're fading so that
            // we prevent excessive redraws
            invalidate = true;
        } else {
            // We're just on -- but we may have been fading before so
            // reset alpha
            cache.scrollBar.setAlpha(255);
        }

        
        final int viewFlags = mViewFlags;

        /**
         * 4 如果存在水平或者垂直滚动条,则逐个进行绘制。( 1 ) 首先调用scrollBar.getSizeO获
         * 得滚动条的大小。对于垂直滚动条而言,大小就是指track或者
         * thumb的宽度;水平方向是指track或 者 thumb的高度,只 有
         * 当 size小 于 0 时,才 会使用X M L 中
         * android:scrollbarSize 属性的值。( 2 ) 绘制水平滚动条。( 3 ) 绘制
         * 垂直滚动条。绘制时,首先回调computeVerticalRange()等三个函数,获得当前的range、
         * offset及 extent值,然后将这三个值设置到scrollBar中。这就是为什么滚动条会“滚动” 的原因。自定
         * 义视图的设计者应该重载这三个computeXXXO函数,并在函数实现中根揮自定义的滚动情况返回相应
         * 的值,从而使得View系统能够绘制出具有正确位置的滚动条。源码中有一段注释是关于RTL语言的,
         * RTL是指从右向左阅读的语言。设置完这三个值后,回 调 onDrawVerticalScrollBarO函数,
         *
         * 即首先设置滚动条对应的剪切区,然后调用scroUBar的 draw()函数将其绘制到剪切区中。
         */
        final boolean drawHorizontalScrollBar =
            (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
        final boolean drawVerticalScrollBar =
            (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
            && !isVerticalScrollBarHidden();

        if (drawVerticalScrollBar || drawHorizontalScrollBar) {
            final int width = mRight - mLeft;
            final int height = mBottom - mTop;

            final ScrollBarDrawable scrollBar = cache.scrollBar;
            int size = scrollBar.getSize(false);
            if (size <= 0) {
                size = cache.scrollBarSize;
            }

            final int scrollX = mScrollX;
            final int scrollY = mScrollY;
            final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;

            int left, top, right, bottom;
            
            if (drawHorizontalScrollBar) {
                scrollBar.setParameters(computeHorizontalScrollRange(),
                                        computeHorizontalScrollOffset(),
                                        computeHorizontalScrollExtent(), false);
                final int verticalScrollBarGap = drawVerticalScrollBar ?
                        getVerticalScrollbarWidth() : 0;
                top = scrollY + height - size - (mUserPaddingBottom & inside);                         
                left = scrollX + (mPaddingLeft & inside);
                right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
                bottom = top + size;
                onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
                if (invalidate) {
                    invalidate(left, top, right, bottom);
                }
            }
            /**
             * 以上步骤已经完成了一次绘制,但如果当前滚动条正处于滚动状态,则需要继续调用invalidateO
             * 发起一次重绘消息。而判断是否处于滚动状态的变量是invalidate,其值正是当cache状态为FADDING
             * 时被赋值为true。调 用 invalidateO时,参数对应的矩形区仅仅是滚动条所在的区域。
             * 至此,滚动条绘制就完成了。
             */
            if (drawVerticalScrollBar) {
                scrollBar.setParameters(computeVerticalScrollRange(),
                                        computeVerticalScrollOffset(),
                                        computeVerticalScrollExtent(), true);
                // TODO: Deal with RTL languages to position scrollbar on left
                left = scrollX + width - size - (mUserPaddingRight & inside);
                top = scrollY + (mPaddingTop & inside);
                right = left + size;
                bottom = scrollY + height - (mUserPaddingBottom & inside);
                onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
                if (invalidate) {
                    invalidate(left, top, right, bottom);
                }
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值