View的弹性滑动

弹性滑动,就是将一个大的滑动分成若干个小的滑动,并在一个事件段内,完成。实现方式有多种:

1.使用Scroller

对于Scroller 在View的基础知识中有过一点介绍,看一下源码,是如何实现弹性滑动的

	Scroller scroller = new Scroller(mContext);
	//缓慢的移动到指定位置
	private void smoothScrollTo(int destX,int destY){
		int scrollX = getScrollX();
		int deltaX = destX - sCrollX;
		//1000ms滑向destX,效果就是慢慢移动
		mScroller.startScroll(scrollX,0,deltaX,0,1000);
		invalidate();
		}
	

上面是一个典型的实现方式,先构造一个Scroller对象,并且调用startScroll方法时,Scroller内部没做什么,只保存了我们传递的参数,这几个参数可以看一下startScroll()方法,如下:

/**
     * 
     * @param startX 起始位置x
     * @param startY 起始位置Y
     * @param dx  x滑动距离
     * @param dy  y滑动距离
     * @param duration  滑动时间
     */
public void startScroll(int startX,int startY,int dx,int dy,int duration){
		mMode = SCROLL_MODE;
		mFinished = false;
		mDuration = duration;
		mStartTime = AnimationUtils.currentAnimationTimeMillis();
		mStartX = startX;
		mStartY = startY;
		mFinalX = startX + dx;
		mFinalY = startY+dy;
		mDetalX = dx;
		mDetalY = dy;
		mDurationReciprocal = 1.0f/(float)mDuration;
	}

注意这个滑动的是View的内容,并非View本身,startScroll方法并没有做View的滑动,那为什么View会滑动了?其实主要是invalidate会导致View重绘,而在View的draw方法中,又会调用computeScroll,但此方法在view中是空实现,需要我们自己实现,如下代码:

@override
	public void computeScroll(){
		if(mScroller.computeScrollOffset()){
			scrollTo(mScrollder.getCurrX(),mScroller.getCurrY());
			postInvalidate();	
		}
	}

正因为这个computScroll()方法,view才会弹性滑动。实现过程View重绘,会在draw方法中调用computeScroll,而computeScroll又会去像Scroller获取当前的scrollX和scrollY的值,然后再调用scrollTo对View移动,接着又会调用postInvalidate方法进行第二次重绘View,这次和第一次一样,如此反复,直到整个滑动过程结束。
再看一下Scroller的computeScrollOffset方法:

 /**
     * Call this when you want to know the new location.  If it returns true,
     * the animation is not yet finished.
     */ 
    public boolean computeScrollOffset() {
       ...

        int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
    
        if (timePassed < mDuration) {
            switch (mMode) {
            case SCROLL_MODE:
                final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
                mCurrX = mStartX + Math.round(x * mDeltaX);
                mCurrY = mStartY + Math.round(x * mDeltaY);
                break;
                ...
               }
           }
           
        return true;
    }

这个方法会根据时间的变化,通过百分比计算出当前的scrollX、scrollY的值,这个类似动画的插值器的概念。返回值位true,表示还没滑动完,false,表示滑动结束。

2、通过动画

动画本身是一个渐近的过程,所以它实现的滑动也是具有弹性效果,比如将一个View的内容在100ms内向左移动100像素

ObjectAnimation .ofFloat(targetView,"translationX",0,100).setDuration(100).start();

使用动画的特性来实现一些动画不能实现的效果,用ScrollTo实现弹性滑动:

final int startX = 0;
final int deltaX = 100;
ValueAnimator animator = ValueAnimator.ofInt(0,1).setDuration(1000);
animation.addUpdateListener(new Animator animator(){
	@override
	public void onAnimationUpdate(ValueAnimator animator){
			float fraction = animator.getAnimateFraction();
			mButton1.scrollTo(startX,+(int)(deltaX+fraction),0);
		}
	)};
	animator.start();

发现这个实现过程和Scroller的实现过程类似,也是在一个时间段,通过一个百分比配合scrollerTo方法,实现弹性滑动效果。采取这种方式,也可以在哦你AnimationUpdate方法中做一些其它我们想要的操作和动画效果。

3、使用演示策略

延时策略就是通过发送一系列延时消息达到一种渐进的效果,可使用Handler或者View的postDelayed,或者sleep方法。下面已Handler为例,将View的内容想做移动100像素:

private static final int MESSAGE_SCROLL_TO = 1;
private static final int FRAME_COUNT = 30;
private static final int DELAYED_TIME = 33;
private int mCount = 0;
@SuppressLint(HandlerLeak)
private Handler mHandler = new Handler(){
	public void hangleMessage(Message msg){
		switch(msg.what){
			case:MESSAGE_SCROLL_TO:
			mCount++;
			if(mCount <+ FRAME_COUNT){
				float fraction = mcount / (float) FRAME_COUNT;
				int scrllX = (int)(fraction * 100);
				mButton1.scrollTo(scrolX, 0);
				mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,DELSYED_TIME);
			}
			break;
		}
		default:
		break;
		}
	};
};

特别声明:内容总结来源《Android开发艺术探索》,仅记录学习,如有侵权或不对之处,还请告知,定当删除或改正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这个Bug有点难搞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值