以下是部分代码:

//设置动画资源
mAnimEnter = AnimationUtils.loadAnimation(this, R.anim.pickerview_slide_in_bottom);
mAnimExit = AnimationUtils.loadAnimation(this, R.anim.pickerview_slide_out_bottom);

//recyclerView 监听上下滑动的事件
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        //处理上下滑动时,显示和隐藏底部控件,同时渐变状态栏颜色
        handlerRecyclerViewScrollStatus(recyclerView, dx, dy);
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }
});

此处我用的是View动画,定义的xml资源文件:

 view_slide_in_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">

  <translate
      android:duration="@integer/animation_default_duration"
      android:fromXDelta="0%"
      android:toXDelta="0%"
      android:fromYDelta="200%"
      android:toYDelta="0%"/>
</set>

view_slide_out_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">

  <translate
      android:duration="@integer/animation_default_duration"
      android:fromXDelta="0%"
      android:toXDelta="0%"
      android:fromYDelta="0%"
      android:toYDelta="200%"/>
</set>

需要注意的是toYDelta设置成100%一般是不满足的,因为Button需要设置padding和margin值的.

 

然后是具体实现滑动的事件的的代码

private void handlerRecyclerViewScrollStatus(RecyclerView recyclerView, int dx, int dy) {
    //根据滑动方向去设置不同的事件
    if (dy > 0 ) { 

        if (recyclerView.getScrollState() == ScrollState.SCROLL_STATE_SETTLING) { //设置此处的目的的为了防止拖拽中的抖动
            setBtAnimExit();
        }

    } else {

        if (recyclerView.getScrollState() == ScrollState.SCROLL_STATE_SETTLING) {//设置此处的目的的为了防止拖拽中的抖动

            setBtAnimEnter();
        }

        int scrollY = getScollYDistance() - 60;//根据滑动距离去计算透明度
        float alpha = scrollY * 1.0f / 500;
       
        //nVewTitleBg是标题栏的文字
        nViewTitleBg.setAlpha(alpha); //设置标题栏文字的透明度,产生渐变效果
        //nStatusBarLine是标题栏的背景
        if (nStatusBarLine != null) {
            nStatusBarLine.setAlpha(alpha);//设置标题栏背景的透明度,产生渐变效果
        }

    }
    Timber.tag("anim");
    Timber.e("dy=" + dy + ",     getScollYDistance()=" + getScollYDistance() + ",...ScrollState" + recyclerView.getScrollState());
}

关于这里的判断是必须的,不然手指一直拖拽的话,动画会不停的一直重复执行,一些app 没有处理这里.当然这样的处理也是有问题的,因为除非用户1秒内不停的小动作滑动,底部的控件无法显示,但是在实际环境中是很少存在的.

如果不去设置的话,会导致,1秒内小范围滑动,动画会多次重复启动.

recyclerView.getScrollState() == ScrollState.SCROLL_STATE_SETTLING

然后是设置动画的代码:

private void setBtAnimExit() {
    if (mBt.getVisibility() == View.GONE) { //防止重复执行
        return;
    }

    mAnimExit.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mBt.setVisibility(View.GONE); //执行以后,就隐藏,如果滑动的距离不够的话,会导致无法隐藏掉控件,所以这里手动设置
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    });
    mBt.startAnimation(mAnimExit);
}

private void setBtAnimEnter() {
    if (mBt.getVisibility() == View.VISIBLE) {
        return;
    }

    mAnimEnter.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mBt.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    });
    mBt.startAnimation(mAnimEnter);
}

 

以上可以用属性动画去设置,遇到的坑应该会更少,因为属性动画是真实的将控件的内容给平移到指定位置了

 

最后别忘记释放资源,看情况是在onPause还是onDestroy里面去释放.最好即时释放,因为android系统执行释放的时机一般比较晚.

@Override
protected void onDestroy() {
    super.onDestroy();

  
    if (mAnimEnter != null) {
        mAnimEnter.cancel();
        mAnimEnter = null;
    }

    if (mAnimExit != null) {
        mAnimExit.cancel();
        mAnimExit = null;
    }

最后是资源文件:

 

资源文件动画的调用

属性动画

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,

    R.anim.property_animator);

set.setTarget(myObject);

set.start();

View动画

ImageView image = (ImageView) findViewById(R.id.image);

Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);

image.startAnimation(hyperspaceJump);

 

帧动画 XML

帧动画的文件是存储在drawble文件当中的,此处实例放在R.drawable.rocket_thrust中:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>

代码中调用

ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();

此处是动画的文档: https://developer.android.google.cn/guide/