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点才能响应。
目录
相关文章
|
1月前
|
缓存 测试技术 Android开发
深入探究Android中的自定义View绘制优化策略
【4月更文挑战第8天】 在Android开发实践中,自定义View的绘制性能至关重要,尤其是当涉及到复杂图形和动画时。本文将探讨几种提高自定义View绘制效率的策略,包括合理使用硬件加速、减少不必要的绘制区域以及利用缓存机制等。这些方法不仅能改善用户体验,还能提升应用的整体性能表现。通过实例分析和性能测试结果,我们将展示如何有效地实现这些优化措施,并为开发者提供实用的技术指南。
|
1月前
|
前端开发 Android开发 开发者
深入探究Android中的自定义View组件开发
【4月更文挑战第3天】 在现代Android应用程序的开发过程中,创建具有独特功能和高度定制化的用户界面是一个常见需求。为此,理解并掌握自定义View组件的开发成为了开发者必备的技能之一。本文将深入探讨如何在Android中创建自定义View,从基础的绘制原理到事件处理机制,再到性能优化技巧,旨在为读者提供一个全面的技术视角,并通过实例代码演示如何实现一个功能丰富、响应迅速的自定义View组件。
|
4月前
|
Android开发 容器
Android UI设计: 什么是View和ViewGroup?
Android UI设计: 什么是View和ViewGroup?
39 0
|
1天前
|
存储 消息中间件 缓存
Android应用开发:实现自定义View的高效绘制
【5月更文挑战第12天】 在Android开发中,创建高性能的自定义视图是一项挑战,它要求开发者深入理解Android的绘图机制以及UI渲染过程。本文将探讨如何优化自定义View的绘制流程,减少不必要的重绘和布局计算,以提升应用的响应速度和流畅度。我们将介绍几种关键策略,包括利用硬件加速、缓存绘制内容和使用高效的数据结构来存储视图状态。通过实例分析和性能对比,读者将学会如何在自己的应用中运用这些技巧,从而打造出更加流畅和响应迅速的用户界面。
|
5月前
|
XML API Android开发
Android 自定义View 之 圆环进度条
Android 自定义View 之 圆环进度条
|
1月前
|
XML 数据可视化 Android开发
深入探究Android中的自定义View组件开发
【4月更文挑战第12天】在安卓应用开发中,创建具有独特交互和视觉表现的自定义View组件是增强用户体验的重要手段。本文将详细阐述如何从头开始构建一个Android自定义View,包括理解View的工作原理、处理绘制流程、事件分发机制以及属性的自定义与管理。通过具体案例分析,我们将一步步实现一个可定制的动态进度条,不仅具备基础功能,还能根据业务需求进行扩展,体现高度的产品个性化。
|
1月前
|
XML Java Android开发
Android控件之基础控件——进度条类的view——TextView、Checkbox复选控件、RadioButton单选控件、ToggleButton开关、SeekBar拖动条、menu、弹窗
Android控件之基础控件——进度条类的view——TextView、Checkbox复选控件、RadioButton单选控件、ToggleButton开关、SeekBar拖动条、menu、弹窗
|
1月前
|
前端开发 Android开发 容器
Android View介绍
Android View介绍
20 0
|
7月前
|
SQL 人工智能 移动开发
Android 遍历界面所有的View
本文讲述如何遍历获取页面中所有的view,并输出对应的id,textview文本内容,imageview实际大小及设置的图片大小。 可用于检测android应用中的大图。
|
5月前
|
XML API Android开发
Android 自定义View 之 Dialog弹窗
Android 自定义View 之 Dialog弹窗