《Android艺术开发探索》学习笔记之View的事件体系(View的弹性滑动)

实现弹性滑动的共同的思想:将一次大滑动分成若干次小的滑动并在一个时间段内完成。

弹性滑动方式:Scroller、动画、延时策略。

Scroller

以上就是Scroller的典型使用方法。

Sroller工作原理:当我们构造一个Scroller对象并且调用它的startScroll方法时,Scroller内部其实什么也没有做,它只是保存了我们传递的几个参数。仅仅调用startScroll是无法让View滑动的,因为它并没有做滑动相关的事情,接着就是调用invalidate方法,invalidate方法会导致View重绘,在View的draw方法中又会去调用computeScroll方法,computeScroll方法在View中是一个空实现,因此需要我们自己去实现,上图中的代码已经实现好了。

也就是说:当View重绘后会在draw方法中调用computeScroll,而computeScroll又会去向Scroller获取当前的ScrollX和ScrollY;然后通过ScrollTo方法实现滑动,接着又调用postInvalidate方法进行第二次重绘,这一次重绘的过程跟第一次重绘的过程一样,还是会导致computeScroll方法被调用,然后继续向Scroller获取当前的scrollX和ScrollY,并通过scrollTo方法滑动到新的位置,如此反复,直到整个过程结束。

概括:Scroller本身并不能实现View的滑动,它需要配合View的computeScroll方法才能完成弹性滑动的效果,它不断的让View重绘,而每一次重绘距滑动起始会有一个时间间隔,通过这个时间间隔Scroller就可以得出View当前的滑动位置,知道了滑动位置就可以通过ScrollTo方法完成View的滑动。就这样,View的每一次重绘都会导致View进行小幅度的滑动,而多次小幅度的滑动就组成了弹性滑动,这就是Scroller的工作机制。

通过动画

动画本身就是一种渐近的过程,通过它来实现的滑动天然就具有弹性效果。

ObjectAnimator.ofFloat(mTest,"translationX",0,100).setDuration(100).start();
复制代码

使用动画监听addUpdateListener实现一些动画不能实现的效果:

private int startX = 0;
private int deltaX = 100;

private void myAnimation() {
final ValueAnimator animator = ValueAnimator.ofInt(0, 1).setDuration(1000);
 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float fraction = animator.getAnimatedFraction();
            mTest.scrollTo(startX + (int) (deltaX * fraction), 0);
        }
     });
    animator.start();
}
复制代码

以上就是在1s内完成整个动画效果,注意这里是滑动View的内容,并不是View本身。

使用延时策略
public class ViewScrollerActivity extends AppCompatActivity {

    private Button mTest;
    private static final int MESSAGE_SCROLL_TO = 0;
    private static final int FRAME_COUNT = 30;
    private static final int DELAYED_TIME = 33;
    private int mCount = 0;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MESSAGE_SCROLL_TO:{
                    mCount ++;
                    if (mCount <= FRAME_COUNT){
                        float fraction = mCount/(float)FRAME_COUNT;
                        int scrollX = (int)(fraction*100);
                        mTest.scrollTo(scrollX,0);
                        mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,DELAYED_TIME);
                    }
                    break;
                }
                default:
                    break;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_scroller);
        mTest = (Button) this.findViewById(R.id.test);

        mTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,DELAYED_TIME);
            }
        });

    }

}

复制代码

xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context="com.main.scroll.ViewScrollerActivity">

    <Button
        android:id="@+id/test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="test"/>

</LinearLayout>

复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值