1. 程式人生 > >ActionBar隨滑動顯示隱藏

ActionBar隨滑動顯示隱藏

之前寫過一個ActionBar隨著列表或者其他滑動而顯示或者隱藏的文章,前段時間,有了新的想法了,所以,更新一下程式碼,把新的思路放上來。(最新的android design support包當中,已經有類似功能的封裝了,但是貌似不夠靈活,還沒有仔細研究那個包呢)

視訊演示如下:

基本思路:

主要是利用RecyclerView 的OnScrollListener的兩個回撥函式OnScrollStateChange和OnScrolled,去控制指定view的顯示,位置和隱藏,再利用動畫,使動作更為流暢。

在程式碼中,有兩個類:TopTrackListener和BottomTrackListener,分別用來控制向上隱藏和向下隱藏。這樣的思路,可以移植到其他的可以隨手滑動的控制元件上。

廢話不多說,以TopTrackListener為例,程式碼如下:

public class TopTrackListener extends RecyclerView.OnScrollListener {

    private static final String TAG = TopTrackListener.class.getSimpleName();

    private int mLastDy = 0;
    private int mTotalDy = 0;

    private View mTargetView = null;

    private ObjectAnimator mAnimator = null;

    private boolean isAlreadyHide = false, isAlreadyShow = false;

    public TopTrackListener(View target) {
        if (target == null) {
            throw new IllegalArgumentException("target shouldn't be null");
        }
        mTargetView = target;
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        switch (newState) {
            case RecyclerView.SCROLL_STATE_IDLE:
                final float transY = mTargetView.getTranslationY();
                int distance = -mTargetView.getBottom();

                if (transY == 0 || transY == distance) {
                    return;
                }
                if (mLastDy > 0) {
                    mAnimator = animateHide(mTargetView);
                } else {
                    mAnimator = animateShow(mTargetView);
                }
                break;
            case RecyclerView.SCROLL_STATE_DRAGGING:
                if (mAnimator != null && mAnimator.isRunning()) {
                    mAnimator.cancel();
                }
                break;
            case RecyclerView.SCROLL_STATE_SETTLING:
                break;
        }
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        mTotalDy -= dy;
        mLastDy = dy;
        final float transY = mTargetView.getTranslationY();
        float newTransY;
        int distance = -mTargetView.getBottom();

        if (mTotalDy >= distance && dy > 0) {
            return;
        }

        if (isAlreadyHide && dy > 0) {
            return;
        }

        if (isAlreadyShow && dy < 0) {
            return;
        }

        newTransY = transY - dy;
        if (newTransY < distance) {
            newTransY = distance;
        } else if (newTransY == distance) {
            return;
        } else if (newTransY > 0) {
            newTransY = 0;
        } else if (newTransY == 0) {
            return;
        }

        mTargetView.setTranslationY(newTransY);
        isAlreadyHide = newTransY == distance;
        isAlreadyShow = newTransY == 0;

    }

    private ObjectAnimator animateHide (View targetView) {
        int distance = -targetView.getBottom();
        return animationFromTo(targetView, targetView.getTranslationY(), distance);
    }

    private ObjectAnimator animateShow (View targetView) {
        return animationFromTo(targetView, targetView.getTranslationY(), 0);
    }

    private ObjectAnimator animationFromTo (View view, float start, float end) {
        String propertyName = "translationY";
        ObjectAnimator animator = ObjectAnimator.ofFloat(view, propertyName, start, end);
        animator.start();
        return animator;
    }

}