Scroller类源码解析及其应用(二)

接上一篇文章的内容,这篇文章主要是Scroller类的应用,在讲具体实例之前,我还有顺便提一个Scroller的问题。

就是fling()方法和startScroll()方法的区别,其实确保已经在上篇文章说得很清楚(注释里面)。

fling没有设置起点坐标和终点坐标,而是根据滑动的起始速度来计算最后会到达的坐标位置。

在了解scroller的使用之前,我们来看一下调用示意图

据我们的了解,我们computeScroll()方法将会在draw()方法中调用。对于一个groupView而言,每次重绘,它会先调用draw()方法,然后调用dispatchDraw(),杂这个方法里面,会逐个对子控件调用drawChild()方法,最后在drawChild()方法里面,我们看到了对computeScroll()方法的调用

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {…………if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) &&(child.mPrivateFlags & DRAW_ANIMATION) == 0) {return more;}child.computeScroll();final int sx = child.mScrollX;final int sy = child.mScrollY;boolean scalingRequired = false;Bitmap cache = null;…………}下面再来说一下写滑动效果步骤

对于步骤一:假设我们只是需要简单的拖动,那么我们在onTouchEvent()方法里面,先获取down的坐标,然后每次move,获得新坐标,再利用scrollBy()方法传入就可以实现拖动的效果

对于步骤二:我们往往利用Scroller是用于当手指离开屏幕以后,滑动效果还会继续进行,所以我们最好在up的时候,调用startScroll()方法。那么怎么在手指离开以后,还知道目标坐标呢,那当然是Scroller的作用,它就是替我们计算坐标的工具。当然我们每次要指定最终目的坐标,这个根据现实的要求不同而不同,在接下来的实例中,目的坐标是下一屏的位置

对于步骤三:在computeScroll()方法里面,不断的scrollTo

对于步骤四:首先我们要清楚多点触控的一个重要调用顺序

举例来讲:当我们放一个食指到屏幕上时,触发ACTION_DOWN事件;再放一个拇指到屏幕上,触发ACTION_POINTER_DOWN事件;此时再把食指或拇指放开,都会触发ACTION_POINTER_UP事件;再放开最后一个手指,触发ACTION_UP事件;而同时在整个过程中,ACTION_MOVE事件会一直不停地被触发。

具体来说,第四步就是维护一个唯一的手指,我们首先维护第一个按下的手指(在Action_down里面获得),然后每次move,都是依据这个手指通过的坐标。最后action_pointer_up的时候,,判断是不是我们维护的手指离开了,如果是,就需要换一只来维护(如果有的话)

下面是一个用于屏幕切换的例子代码

看一下截图(由于是滑动的,没办法截到动态)

我自定义了一个控件,下面是初始化代码

public class MyView extends ViewGroup {public MyView(Context context) {        super(context);            init(context);    }        public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }        public MyView(Context context, AttributeSet attrs) {        super(context, attrs);                init(context);    }    public void init(Context context){        this.context = context;        mScroller = new Scroller(context);        l1 = new LinearLayout(context);        l1.setBackgroundColor(Color.GREEN);        l2 = new LinearLayout(context);        l2.setBackgroundColor(Color.RED);;        l3 = new LinearLayout(context);                l3.setBackgroundColor(Color.YELLOW);        addView(l1);addView(l2);addView(l3);            }也就是说有三个linearLayout组成myView,我们在onMeassure()方法里面,让每个linearLayout都占据一个屏幕大小@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int w = MeasureSpec.getSize(widthMeasureSpec);int h = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(w, h);int childcount = getChildCount();for(int i=0;i<childcount;i++){View child = getChildAt(i);child.measure(MainActivity.screenWidth, MainActivity.screenHeight);}}在onlayout()方法里面,为三个linearLayout设置位置(按顺序),这样我们每次就只能看到一个@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int startX = 0;int childcount = getChildCount();for(int i=0;i<childcount;i++){View child = getChildAt(i);child.layout(startX, 0, startX+MainActivity.screenWidth, MainActivity.screenHeight);startX += MainActivity.screenWidth;}}然后我们按照上面的说法,开始处理滑动时间,首先是downfloat oldX = 0;private VelocityTracker mVelocityTracker;private int mPointerId;@Overridepublic boolean onTouchEvent(MotionEvent event) {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(event);int action = event.getActionMasked();switch(action){case MotionEvent.ACTION_DOWN:float x = event.getX();// 获取索引为0的手指idmPointerId = event.getPointerId(0);//也就是第一个放下的手指idif(!mScroller.isFinished()){mScroller.abortAnimation();}oldX = x;break;其中有跟多点触控相关的一些代码,大家可以回头再看,这里重要的是,获得down时候的x坐标值,并且强制停止滑动如此锐气,二十后生有之,六旬男子则更多见。

Scroller类源码解析及其应用(二)

相关文章:

你感兴趣的文章:

标签云: