Android Utils - RecyclerView上下滑動通過動畫顯示隱藏底部控件,以及ToolBar狀態欄文字和背景顏色漸變

以下是部分代碼:

//設置動畫資源
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/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章