Android View Scroller问答

简介:

android中的scroll一般是调用View.scrollTo()函数实现的,另外有一个View.scrollBy()其实现也是View.scrollTo()。关于View.scrollTo(),下面有一些问题来探究一下,本文所查看的代码是android4.2.2的源代码。

  • 问:View.scrollTo()的原理是什么?
    答:在android.view.View.java中有两个变量mScrollX和mScrollY,两个变量的定义如下:

    /**
     * The offset, in pixels, by which the content of this view is scrolled
     * horizontally.
     */
    protected int mScrollX;
    
    /**
     * The offset, in pixels, by which the content of this view is scrolled
     * vertically.
     */
    protected int mScrollY;
    


    在View的绘制过程中,会根据这两个值对里面的内容进行偏移。View.draw()中的代码片段如下:

    int left = mScrollX + paddingLeft;
    int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
    int top = mScrollY + getFadeTop(offsetRequired);
    int bottom = top + getFadeHeight(offsetRequired);
    


    在View.scrollTo()的作用就是就是改变这两个变量,从而引起View的content位置发生变化。

  • 问:Scroll是否引起Layout的改变?
    答:Scroll只是改变View.mScrollx和View.mScrollY,并且在draw()函数中,根据这两个偏移量进行绘制。所以只是影响draw(),不会引起Layout的改变。
  • 问:如果scroll只是在绘制的时候进行偏移,那么对touch事件的派发是否产生影响,View事件的响应是在scroll前的位置还是scroll后的位置?
    答:事件的分派是在ViewGroup.dispatchTouchEvent()中,查看源码,发现在寻找响应事件的子View时,会算上mScrollX和mScrollY的偏移。所以scroll是会对事件派发产生影响的。View事件的响应是在scroll后的位置。关键代码如下:

    protected boolean isTransformedTouchPointInView(float x, float y, View child,
            PointF outLocalPoint) {
        float localX = x + mScrollX - child.mLeft;
        float localY = y + mScrollY - child.mTop;
        if (! child.hasIdentityMatrix() && mAttachInfo != null) {
            final float[] localXY = mAttachInfo.mTmpTransformLocation;
            localXY[0] = localX;
            localXY[1] = localY;
            child.getInverseMatrix().mapPoints(localXY);
            localX = localXY[0];
            localY = localXY[1];
        }
        final boolean isInView = child.pointInView(localX, localY);
        if (isInView && outLocalPoint != null) {
            outLocalPoint.set(localX, localY);
        }
        return isInView;
    }
    

  • 问:Scroller的作用是什么?
    答:Scroller的作用是帮助Scroll更加顺滑的。如果我们不是想在一段时间内,有A点顺滑的scroll到B点。这样我们就要计算每次draw应该偏移多少,才能达到顺滑的效果。Scroller就是用来帮助计算的。具体的计算方式是在Scroller.computeScrollOffset()函数中。代码如下:

    public boolean computeScrollOffset() {
    if (mFinished) {
        return false;
    }
    
    int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
    
    if (timePassed < mDuration) {
        switch (mMode) {
        case SCROLL_MODE:
            float x = timePassed * mDurationReciprocal;
    
            if (mInterpolator == null)
                x = viscousFluid(x); 
            else
                x = mInterpolator.getInterpolation(x);
    
            mCurrX = mStartX + Math.round(x * mDeltaX);
            mCurrY = mStartY + Math.round(x * mDeltaY);
            break;
        case FLING_MODE:
            final float t = (float) timePassed / mDuration;
            final int index = (int) (NB_SAMPLES * t);
            float distanceCoef = 1.f;
            float velocityCoef = 0.f;
            if (index < NB_SAMPLES) {
                final float t_inf = (float) index / NB_SAMPLES;
                final float t_sup = (float) (index + 1) / NB_SAMPLES;
                final float d_inf = SPLINE_POSITION[index];
                final float d_sup = SPLINE_POSITION[index + 1];
                velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
                distanceCoef = d_inf + (t - t_inf) * velocityCoef;
            }
    
            mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
    
            mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
            // Pin to mMinX <= mCurrX <= mMaxX
            mCurrX = Math.min(mCurrX, mMaxX);
            mCurrX = Math.max(mCurrX, mMinX);
    
            mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
            // Pin to mMinY <= mCurrY <= mMaxY
            mCurrY = Math.min(mCurrY, mMaxY);
            mCurrY = Math.max(mCurrY, mMinY);
    
            if (mCurrX == mFinalX && mCurrY == mFinalY) {
                mFinished = true;
            }
    
            break;
        }
    }
        else {
            mCurrX = mFinalX;
            mCurrY = mFinalY;
            mFinished = true;
        }
        return true;
    }
    

  • 问:Scroll和ValueAnimator的区别是什么?
    答:ValueAnimator的本质是在一段时间内,按照一定的规律去改变一个值。而scroll就是改变mScrollX和mScrollY的值。所以理论上也可以用ValueAnimator来改变mScrollX和mScrollY,从而达到scroll的目的。
  • 问:Scroll和Animation的区别是什么?
    答:animation也是通过在draw函数里面实现的,但是animation只是改变了绘制的位置,并没有影响到事件的响应。所以当一个View从A点通过Animation动画移动到B点,View的事件继续在A点才能响应。
目录
相关文章
|
12天前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
42 0
|
1天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
11 2
|
13天前
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
27 3
|
12天前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
1月前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
1月前
|
Android开发
Android中SurfaceView的双缓冲机制和普通View叠加问题解决办法
本文介绍了 Android 平台上的 SurfaceView,这是一种高效的图形渲染控件,尤其适用于视频播放、游戏和图形动画等场景。文章详细解释了其双缓冲机制,该机制通过前后缓冲区交换来减少图像闪烁,提升视觉体验。然而,SurfaceView 与普通 View 叠加时可能存在 Z-Order 不一致、同步问题及混合渲染难题。文中提供了使用 TextureView、调整 Z-Order 和创建自定义组合控件等多种解决方案。
89 9
|
1月前
|
Android开发 容器
Android经典实战之如何获取View和ViewGroup的中心点
本文介绍了在Android中如何获取`View`和`ViewGroup`的中心点坐标,包括计算相对坐标和屏幕上的绝对坐标,并提供了示例代码。特别注意在视图未完成测量时可能出现的宽高为0的问题及解决方案。
39 7
|
2月前
|
XML 搜索推荐 Android开发
安卓开发中的自定义View组件实践
【8月更文挑战第30天】探索Android世界,自定义View是提升应用界面的关键。本文以简洁的语言带你了解如何创建自定义View,从基础到高级技巧,一步步打造个性化的UI组件。
|
2月前
|
API Android开发 开发者
Android经典实战之使用ViewCompat来处理View兼容性问题
本文介绍Android中的`ViewCompat`工具类,它是AndroidX库核心部分的重要兼容性组件,确保在不同Android版本间处理视图的一致性。文章列举了设置透明度、旋转、缩放、平移等功能,并提供了背景色、动画及用户交互等实用示例。通过`ViewCompat`,开发者可轻松实现跨版本视图操作,增强应用兼容性。
107 5
|
2月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
98 2