Android中滑屏实现----触摸滑屏以及Scroller类详解 .

转:http://blog.csdn.net/qinjuning/article/details/7419207

知识点一:  关于scrollTo()和scrollBy()以及偏移坐标的设置/取值问题

scrollTo()和scrollBy()这两个方法的主要作用是将View/ViewGroup移至指定的坐标中,并且将偏移量保存起来。另外:

mScrollX 代表X轴方向的偏移坐标

mScrollY 代表Y轴方向的偏移坐标

关于偏移量的设置我们可以参看下源码:

package com.qin.customviewgroup;

public class View {
....
protected int mScrollX; //该视图内容相当于视图起始坐标的偏移量 , X轴 方向
protected int mScrollY; //该视图内容相当于视图起始坐标的偏移量 , Y轴方向
//返回值
public final int getScrollX() {
return mScrollX;
}
public final int getScrollY() {
return mScrollY;
}
public void scrollTo(int x, int y) {
//偏移位置发生了改变
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x; //赋新值,保存当前便宜量
mScrollY = y;
//回调onScrollChanged方法
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
invalidate(); //一般都引起重绘
}
}
}
// 看出原因了吧 。。 mScrollX 与 mScrollY 代表我们当前偏移的位置 , 在当前位置继续偏移(x ,y)个单位
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
//...
}

于是,在任何时刻我们都可以获取该View/ViewGroup的偏移位置了,即调用getScrollX()方法和getScrollY()方法

知识点二: Scroller类的介绍

在初次看Launcher滑屏的时候,我就对Scroller类的学习感到非常蛋疼,完全失去了继续研究的欲望。如今,没得办法,

得重新看Launcher模块,基本上将Launcher大部分类以及功能给掌握了。当然,也花了一天时间来学习Launcher里的滑屏实现

,基本上业是拨开云雾见真知了。

我们知道想把一个View偏移至指定坐标(x,y)处,利用scrollTo()方法直接调用就OK了,但我们不能忽视的是,该方法本身

来的的副作用:非常迅速的将View/ViewGroup偏移至目标点,而没有对这个偏移过程有任何控制,对用户而言可能是不太

友好的。于是,基于这种偏移控制,Scroller类被设计出来了,该类的主要作用是为偏移过程制定一定的控制流程(后面我们会

知道的更多),从而使偏移更流畅,更完美。

可能上面说的比较悬乎,道理也没有讲透。下面我就根据特定情景帮助大家分析下:

情景: 从上海如何到武汉?

普通的人可能会想,so easy : 飞机、轮船、11路公交车...

文艺的人可能会想,  小 case : 时空忍术(火影的招数)、翻个筋斗(孙大圣的招数)...

不管怎么样,我们想出来的套路可能有两种:

1、有个时间控制过程才能抵达(缓慢的前进)                              -----     对应于Scroller的作用

假设做火车,这个过程可能包括: 火车速率,花费周期等;

2、瞬间抵达(超神太快了,都眩晕了,用户体验不太好)                     ------   对应于scrollTo()的作用

  模拟Scroller类的实现功能:

 

假设从上海做动车到武汉需要10个小时,行进距离为1000km ,火车速率200/h 。采用第一种时间控制方法到达武汉的

整个配合过程可能如下:

我们每隔一段时间(例如1小时),计算火车应该行进的距离,然后调用scrollTo()方法,行进至该处。10小时过完后,

我们也就达到了目的地了。

相信大家心里应该有个感觉了。我们就分析下源码里去看看Scroller类的相关方法.

其源代码(部分)如下: 路径位于 \frameworks\base\core\java\android\widget\Scroller.java

public class Scroller  {

    private int mStartX;    //起始坐标点 ,  X轴方向
    private int mStartY;    //起始坐标点 ,  Y轴方向
    private int mCurrX;     //当前坐标点  X轴, 即调用startScroll函数后,经过一定时间所达到的值
    private int mCurrY;     //当前坐标点  Y轴, 即调用startScroll函数后,经过一定时间所达到的值

    private float mDeltaX;  //应该继续滑动的距离, X轴方向
    private float mDeltaY;  //应该继续滑动的距离, Y轴方向
    private boolean mFinished;  //是否已经完成本次滑动操作, 如果完成则为 true

    //构造函数
    public Scroller(Context context) {
        this(context, null);
    }
    public final boolean isFinished() {
        return mFinished;
    }
    //强制结束本次滑屏操作
    public final void forceFinished(boolean finished) {
        mFinished = finished;
    }
    public final int getCurrX() {
        return mCurrX;
    }
     /* Call this when you want to know the new location.  If it returns true,
     * the animation is not yet finished.  loc will be altered to provide the
     * new location. */
    //根据当前已经消逝的时间计算当前的坐标点,保存在mCurrX和mCurrY值中
    public boolean computeScrollOffset() {
        if (mFinished) {  //已经完成了本次动画控制,直接返回为false
            return false;
        }
        int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
        if (timePassed < mDuration) {
            switch (mMode) {
            case SCROLL_MODE:
                float x = (float)timePassed * mDurationReciprocal;
                ...
                mCurrX = mStartX + Math.round(x * mDeltaX);
                mCurrY = mStartY + Math.round(x * mDeltaY);
                break;
            ...
        }
        else {
            mCurrX = mFinalX;
            mCurrY = mFinalY;
            mFinished = true;
        }
        return true;
    }
    //开始一个动画控制,由(startX , startY)在duration时间内前进(dx,dy)个单位,即到达坐标为(startX+dx , startY+dy)出
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        mFinished = false;
        mDuration = duration;
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mStartX = startX;       mStartY = startY;
        mFinalX = startX + dx;  mFinalY = startY + dy;
        mDeltaX = dx;            mDeltaY = dy;
        ...
    }
}

其中比较重要的两个方法为:

public void startScroll(int startX, int startY, int dx, int dy, int duration)

函数功能说明:根据当前已经消逝的时间计算当前的坐标点,保存在mCurrX和mCurrY值中

函数功能说明:开始一个动画控制,由(startX , startY)在duration时间内前进(dx,dy)个单位,到达坐标为

(startX+dx , startY+dy)处。

PS : 强烈建议大家看看该类的源码,便于后续理解。

知识点二: computeScroll()方法介绍

为了易于控制滑屏控制,Android框架提供了 computeScroll()方法去控制这个流程。在绘制View时,会在draw()过程调用该

方法。因此, 再配合使用Scroller实例,我们就可以获得当前应该的偏移坐标,手动使View/ViewGroup偏移至该处。

computeScroll()方法原型如下,该方法位于ViewGroup.java类中

/**
     * Called by a parent to request that a child update its values for mScrollX
     * and mScrollY if necessary. This will typically be done if the child is
     * animating a scroll using a {@link android.widget.Scroller Scroller}
     * object.
     */由父视图调用用来请求子视图根据偏移值 mScrollX,mScrollY重新绘制
    public void computeScroll() { //空方法 ,自定义ViewGroup必须实现方法体

    }

为了实现偏移控制,一般自定义View/ViewGroup都需要重载该方法 。

其调用过程位于View绘制流程draw()过程中,如下:

    @Override
    protected void dispatchDraw(Canvas canvas){
        ...

        for (int i = 0; i < count; i++) {
            final View child = children[getChildDrawingOrder(count, i)];
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                more |= drawChild(canvas, child, drawingTime);
            }
        }
    }
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        ...
        child.computeScroll();
        ...
    }

Demo说明:

我们简单的复用了之前写的一个自定义ViewGroup,与以前一次有区别的是,我们没有调用scrollTo()方法去进行瞬间

偏移。 本次做法如下:

第一、调用Scroller实例去产生一个偏移控制(对应于startScroll()方法)

第二、手动调用invalid()方法去重新绘制,剩下的就是在 computeScroll()里根据当前已经逝去的时间,获取当前

应该偏移的坐标(由Scroller实例对应的computeScrollOffset()计算而得),

第三、当前应该偏移的坐标,调用scrollBy()方法去缓慢移动至该坐标处。

截图如下:

 

 

                         

 原始界面                                     点击按钮或者触摸屏之后的显示界面

附:由于滑动截屏很难,只是简单的截取了两个个静态图片,触摸的话可以实现左右滑动切屏了。

更多知识点,请看代码注释。。

//自定义ViewGroup , 包含了三个LinearLayout控件,存放在不同的布局位置,通过scrollBy或者scrollTo方法切换
public class MultiViewGroup extends ViewGroup {
    ...
    //startScroll开始移至下一屏
    public void startMove(){
        curScreen ++ ;
        Log.i(TAG, "----startMove---- curScreen " + curScreen);

        //使用动画控制偏移过程 , 3s内到位
        mScroller.startScroll((curScreen-1) * getWidth(), 0, getWidth(), 0,3000);
        //其实点击按钮的时候,系统会自动重新绘制View,我们还是手动加上吧。
        invalidate();
        //使用scrollTo一步到位
        //scrollTo(curScreen * MultiScreenActivity.screenWidth, 0);
    }
    // 由父视图调用用来请求子视图根据偏移值 mScrollX,mScrollY重新绘制
    @Override
    public void computeScroll() {
        // TODO Auto-generated method stub
        Log.e(TAG, "computeScroll");
        // 如果返回true,表示动画还没有结束
        // 因为前面startScroll,所以只有在startScroll完成时 才会为false
        if (mScroller.computeScrollOffset()) {
            Log.e(TAG, mScroller.getCurrX() + "======" + mScroller.getCurrY());
            // 产生了动画效果,根据当前值 每次滚动一点
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

            Log.e(TAG, "### getleft is " + getLeft() + " ### getRight is " + getRight());
            //此时同样也需要刷新View ,否则效果可能有误差
            postInvalidate();
        }
        else
            Log.i(TAG, "have done the scoller -----");
    }
    //马上停止移动,如果已经超过了下一屏的一半,我们强制滑到下一个屏幕
    public void stopMove(){

        Log.v(TAG, "----stopMove ----");

        if(mScroller != null){
            //如果动画还没结束,我们就按下了结束的按钮,那我们就结束该动画,即马上滑动指定位置
            if(!mScroller.isFinished()){

                int scrollCurX= mScroller.getCurrX() ;
                  //判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
                // 这样的一个简单公式意思是:假设当前滑屏偏移值即 scrollCurX 加上每个屏幕一半的宽度,除以每个屏幕的宽度就是
                //  我们目标屏所在位置了。 假如每个屏幕宽度为320dip, 我们滑到了500dip处,很显然我们应该到达第二屏,索引值为1
                //即(500 + 320/2)/320 = 1
                int descScreen = ( scrollCurX + getWidth() / 2) / getWidth() ;

                Log.i(TAG, "-mScroller.is not finished scrollCurX +" + scrollCurX);
                Log.i(TAG, "-mScroller.is not finished descScreen +" + descScreen);
                mScroller.abortAnimation();

                //停止了动画,我们马上滑倒目标位置
                scrollTo(descScreen *getWidth() , 0);
                curScreen = descScreen ; //纠正目标屏位置
            }
            else
                Log.i(TAG, "----OK mScroller.is  finished ---- ");
        }
    }
    ...
}

如何实现触摸滑屏?

其实网上有很多关于Launcher实现滑屏的博文,基本上也把道理阐释的比较明白了 。我这儿也是基于自己的理解,将一些

重要方面的知识点给补充下,希望能帮助大家理解。

想要实现滑屏操作,值得考虑的事情包括如下几个方面:

其中:onInterceptTouchEvent()主要功能是控制触摸事件的分发,例如是子视图的点击事件还是滑动事件。

其他所有处理过程均在onTouchEvent()方法里实现了。

1、屏幕的滑动要根据手指的移动而移动  ---- 主要实现在onTouchEvent()方法中

2、当手指松开时,可能我们并没有完全滑动至某个屏幕上,这是我们需要手动判断当前偏移至去计算目标屏(当前屏或者

前后屏),并且优雅的偏移到目标屏(当然是用Scroller实例咯)。

3、调用computeScroll ()去实现缓慢移动过程。

知识点介绍:

VelocityTracker类

功能:  根据触摸位置计算每像素的移动速率。

常用方法有:

public void addMovement (MotionEvent ev)

功能:添加触摸对象MotionEvent , 用于计算触摸速率。

computeCurrentVelocity (int units)

功能:以每像素units单位考核移动速率。额,其实我也不太懂,赋予值1000即可。

参照源码 该units的意思如下:

参数 units : The units you would like the velocity in.  A value of 1
                             provides pixels per millisecond, 1000 provides
pixels per second, etc.

getXVelocity ()

功能:获得X轴方向的移动速率。

ViewConfiguration类

功能:
获得一些关于timeouts(时间)、sizes(大小)、distances(距离)的标准常量值 。

常用方法:

getScaledEdgeSlop()

说明:获得一个触摸移动的最小像素值。也就是说,只有超过了这个值,才代表我们该滑屏处理了。

getLongPressTimeout()

说明:获得一个执行长按事件监听(onLongClickListener)的值。也就是说,对某个View按下触摸时,只有超过了

这个时间值在,才表示我们该对该View回调长按事件了;否则,小于这个时间点松开手指,只执行onClick监听

我能写下来的也就这么多了,更多的东西参考代码注释吧。
在掌握了上面我罗列的知识后(重点scrollTo、Scroller类),

其他方面的知识都是关于点与点之间的计算了以及触摸事件的分发了。这方面感觉也没啥可写的。

//自定义ViewGroup , 包含了三个LinearLayout控件,存放在不同的布局位置,通过scrollBy或者scrollTo方法切换
public class MultiViewGroup extends ViewGroup {

    private static String TAG = "MultiViewGroup";

    private int curScreen = 0 ;  //当前屏幕
    private Scroller mScroller = null ; //Scroller对象实例

    public MultiViewGroup(Context context) {
        super(context);
        mContext = context;
        init();
    }
    public MultiViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }
    //初始化
    private void init() {
        ...
        //初始化Scroller实例
        mScroller = new Scroller(mContext);
        // 初始化3个 LinearLayout控件
        ...
        //初始化一个最小滑动距离
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }
    // 由父视图调用用来请求子视图根据偏移值 mScrollX,mScrollY重新绘制
    @Override
    public void computeScroll() {
        // TODO Auto-generated method stub
        Log.e(TAG, "computeScroll");
        // 如果返回true,表示动画还没有结束
        // 因为前面startScroll,所以只有在startScroll完成时 才会为false
        if (mScroller.computeScrollOffset()) {
            Log.e(TAG, mScroller.getCurrX() + "======" + mScroller.getCurrY());
            // 产生了动画效果,根据当前值 每次滚动一点
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

            Log.e(TAG, "### getleft is " + getLeft() + " ### getRight is " + getRight());
            //此时同样也需要刷新View ,否则效果可能有误差
            postInvalidate();
        }
        else
            Log.i(TAG, "have done the scoller -----");
    }
    //两种状态: 是否处于滑屏状态
    private static final int TOUCH_STATE_REST = 0;  //什么都没做的状态
    private static final int TOUCH_STATE_SCROLLING = 1;  //开始滑屏的状态
    private int mTouchState = TOUCH_STATE_REST; //默认是什么都没做的状态
    //--------------------------
    //处理触摸事件 ~
    public static int  SNAP_VELOCITY = 600 ;  //最小的滑动速率
    private int mTouchSlop = 0 ;              //最小滑动距离,超过了,才认为开始滑动
    private float mLastionMotionX = 0 ;       //记住上次触摸屏的位置
    //处理触摸的速率
    private VelocityTracker mVelocityTracker = null ;

    // 这个感觉没什么作用 不管true还是false 都是会执行onTouchEvent的 因为子view里面onTouchEvent返回false了
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        Log.e(TAG, "onInterceptTouchEvent-slop:" + mTouchSlop);

        final int action = ev.getAction();
        //表示已经开始滑动了,不需要走该Action_MOVE方法了(第一次时可能调用)。
        //该方法主要用于用户快速松开手指,又快速按下的行为。此时认为是出于滑屏状态的。
        if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {
            return true;
        }

        final float x = ev.getX();
        final float y = ev.getY();

        switch (action) {
        case MotionEvent.ACTION_MOVE:
            Log.e(TAG, "onInterceptTouchEvent move");
            final int xDiff = (int) Math.abs(mLastionMotionX - x);
            //超过了最小滑动距离,就可以认为开始滑动了
            if (xDiff > mTouchSlop) {
                mTouchState = TOUCH_STATE_SCROLLING;
            }
            break;

        case MotionEvent.ACTION_DOWN:
            Log.e(TAG, "onInterceptTouchEvent down");
            mLastionMotionX = x;
            mLastMotionY = y;
            Log.e(TAG, mScroller.isFinished() + "");
            mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;

            break;

        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            Log.e(TAG, "onInterceptTouchEvent up or cancel");
            mTouchState = TOUCH_STATE_REST;
            break;
        }
        Log.e(TAG, mTouchState + "====" + TOUCH_STATE_REST);
        return mTouchState != TOUCH_STATE_REST;
    }
    public boolean onTouchEvent(MotionEvent event){

        super.onTouchEvent(event);

        Log.i(TAG, "--- onTouchEvent--> " );

        // TODO Auto-generated method stub
        Log.e(TAG, "onTouchEvent start");
        //获得VelocityTracker对象,并且添加滑动对象
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        //触摸点
        float x = event.getX();
        float y = event.getY();
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            //如果屏幕的动画还没结束,你就按下了,我们就结束上一次动画,即开始这次新ACTION_DOWN的动画
            if(mScroller != null){
                if(!mScroller.isFinished()){
                    mScroller.abortAnimation();
                }
            }
            mLastionMotionX = x ; //记住开始落下的屏幕点
            break ;
        case MotionEvent.ACTION_MOVE:
            int detaX = (int)(mLastionMotionX - x ); //每次滑动屏幕,屏幕应该移动的距离
            scrollBy(detaX, 0);//开始缓慢滑屏咯。 detaX > 0 向右滑动 , detaX < 0 向左滑动 ,

            Log.e(TAG, "--- MotionEvent.ACTION_MOVE--> detaX is " + detaX );
            mLastionMotionX = x ;
            break ;
        case MotionEvent.ACTION_UP:

            final VelocityTracker velocityTracker = mVelocityTracker  ;
            velocityTracker.computeCurrentVelocity(1000);
            //计算速率
            int velocityX = (int) velocityTracker.getXVelocity() ;
            Log.e(TAG , "---velocityX---" + velocityX);

            //滑动速率达到了一个标准(快速向右滑屏,返回上一个屏幕) 马上进行切屏处理
            if (velocityX > SNAP_VELOCITY && curScreen > 0) {
                // Fling enough to move left
                Log.e(TAG, "snap left");
                snapToScreen(curScreen - 1);
            }
            //快速向左滑屏,返回下一个屏幕)
            else if(velocityX < -SNAP_VELOCITY && curScreen < (getChildCount()-1)){
                Log.e(TAG, "snap right");
                snapToScreen(curScreen + 1);
            }
            //以上为快速移动的 ,强制切换屏幕
            else{
                //我们是缓慢移动的,因此先判断是保留在本屏幕还是到下一屏幕
                snapToDestination();
            }
            //回收VelocityTracker对象
            if (mVelocityTracker != null) {
                mVelocityTracker.recycle();
                mVelocityTracker = null;
            }
            //修正mTouchState值
            mTouchState = TOUCH_STATE_REST ;

            break;
        case MotionEvent.ACTION_CANCEL:
            mTouchState = TOUCH_STATE_REST ;
            break;
        }

        return true ;
    }
    ////我们是缓慢移动的,因此需要根据偏移值判断目标屏是哪个?
    private void snapToDestination(){
        //当前的偏移位置
        int scrollX = getScrollX() ;
        int scrollY = getScrollY() ;

        Log.e(TAG, "### onTouchEvent snapToDestination ### scrollX is " + scrollX);
        //判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
        //直接使用这个公式判断是哪一个屏幕 前后或者自己
        //判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
        // 这样的一个简单公式意思是:假设当前滑屏偏移值即 scrollCurX 加上每个屏幕一半的宽度,除以每个屏幕的宽度就是
        //  我们目标屏所在位置了。 假如每个屏幕宽度为320dip, 我们滑到了500dip处,很显然我们应该到达第二屏
        int destScreen = (getScrollX() + MultiScreenActivity.screenWidth / 2 ) / MultiScreenActivity.screenWidth ;

        Log.e(TAG, "### onTouchEvent  ACTION_UP### dx destScreen " + destScreen);

        snapToScreen(destScreen);
    }
    //真正的实现跳转屏幕的方法
    private void snapToScreen(int whichScreen){
        //简单的移到目标屏幕,可能是当前屏或者下一屏幕
        //直接跳转过去,不太友好
        //scrollTo(mLastScreen * MultiScreenActivity.screenWidth, 0);
        //为了友好性,我们在增加一个动画效果
        //需要再次滑动的距离 屏或者下一屏幕的继续滑动距离

        curScreen = whichScreen ;
        //防止屏幕越界,即超过屏幕数
        if(curScreen > getChildCount() - 1)
            curScreen = getChildCount() - 1 ;
        //为了达到下一屏幕或者当前屏幕,我们需要继续滑动的距离.根据dx值,可能想左滑动,也可能像又滑动
        int dx = curScreen * getWidth() - getScrollX() ;

        Log.e(TAG, "### onTouchEvent  ACTION_UP### dx is " + dx);

        mScroller.startScroll(getScrollX(), 0, dx, 0,Math.abs(dx) * 2);

        //由于触摸事件不会重新绘制View,所以此时需要手动刷新View 否则没效果
        invalidate();
    }
    //开始滑动至下一屏
    public void startMove(){
        ...
    }
    //理解停止滑动
    public void stopMove(){
        ...
    }
    // measure过程
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       ...
    }
    // layout过程
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        ...
    }
}
时间: 2024-10-20 04:08:05

Android中滑屏实现----触摸滑屏以及Scroller类详解 .的相关文章

Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解

Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解

Android中moveTo、lineTo、quadTo、cubicTo、arcTo详解(实例)

最近在写android画图经常用到这几个什么什么To,一开始还真不知道cubicTo这个方法,更不用说能不能分清楚它们了,所以特此来做个小笔记,记录下moveTo.lineTo.quadTo.cubicTo.arcTo的作用,在自定义view的时候经常用到.接下来也会分享下这几天写的几个东西.相信对于新手也会有点帮助,高手也帮忙看看有没错,欢迎吐槽吐槽. 2.moveTo moveTo 不会进行绘制,只用于移动移动画笔.结合以下方法进行使用. 3.lineTo lineTo 用于进行直线绘制.

Android中moveTo、lineTo、quadTo、cubicTo、arcTo详解

1.Why 最近在写android画图经常用到这几个什么什么To,一开始还真不知道cubicTo这个方法,更不用说能不能分清楚它们了,所以特此来做个小笔记,记录下moveTo.lineTo.quadTo.cubicTo.arcTo的作用,在自定义view的时候经常用到.接下来也会分享下这几天写的几个东西.相信对于新手也会有点帮助,高手也帮忙看看有没错,欢迎吐槽吐槽. 2.moveTo moveTo 不会进行绘制,只用于移动移动画笔.结合以下方法进行使用. 3.lineTo lineTo 用于进行

android自定义控件系列----Scroller类详解

说在前面的话: 为什么要来说Scroller这个类呢?这个类到底是拿来干什么的呢?如果你看了ListView这类控件那么你肯定会发现里面有一个Sroller类,其实它的作用就是辅助记录和计算我们滑动的距离和速度这些.从而让我们在自定义控件的时候可以方便的做一些滑动和回弹的动画,为什么呢?因为Sroller类都给你计算好了嘛. 类分析 public class Scroller { private int mMode; private int mStartX; private int mStart

Android中三种超实用的滑屏方式汇总(转载)

Android中三种超实用的滑屏方式汇总 现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于前段时间项目的需要,所以也对其研究了一下,总的来说滑屏实现有三种方式:(至于其他的实现方式目前后还没碰到...) 1.ViewPager 2.ViewFlipper 3.ViewFlow 一.ViewPager 官方文档介绍:http://developer.android.com/reference/

Android中利用命令行进行截屏并导出到电脑上

声明:本博客为原创博客,未经允许,不得转载!原文链接为http://blog.csdn.net/bettarwang/article/details/27819525 大多数人最常用的截屏方法可能就是利用手机的快捷按键了,但是那样如果要导入到电脑中效率会比较低.实际上有更好的截屏方式,最简单的当然就是利用Eclipse中的DDMS进行截屏了,点击"Screen Capture"按钮后等待10多秒,然后就可直接利用Save按钮保存到电脑中. 显然,由于要进行图片显示的原因,在DDMS中会

Android技术18:Android中Adapter类详解

1.Adapter设计模式 Android中adapter接口有很多种实现,例如,ArrayAdapter,BaseAdapter,CursorAdapter,SimpleAdapter,SimpleCursorAdapter等,他们分别对应不同的数据源.例如,ArrayAdater对应List和数组数据源,而CursorAdapter对应Cursor对象(一般从数据库中获取的记录集).这些Adapter都需要getView方法返回当前列表项显示的View对象.当Model发生改变时,会调用Ba

Android中内容观察者的使用---- ContentObserver类详解

  转载请注明出处:http://blog.csdn.net/qinjuning 前言: 工作中,需要开启一个线程大量的查询某个数据库值发送了变化,导致的开销很大,后来在老大的指点下,利用了 ContentObserver完美的解决了该问题,感到很兴奋,做完之后自己也对ContentObserver做下总结. ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于 数据库技术中的触发器(Trigger),当ContentObs

Android学习Scroller(五)——详解Scroller调用过程以及View的重绘

MainActivity如下: package cc.ww; import android.os.Bundle; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.app.Activity;