How to hide and show the Android ActionBar like in

2019-09-06 20:46发布

问题:

I wnat to show and hide the Android ActionBar when the user scrolls the screen. I found some examples, like this question in SO. But the code showed in this question and its answer makes the action hides after the list have scrolled some pixels, and I want to make this scroll like the Inbox App by Google, that is the action bar is pulled by the Layout according to the user scroll the screen up or down, in other words, I want to show/hide the action bar at the same time the user scroll down/up.

Someone face a problema like this? Some idea?

回答1:

super simple:

  1. ditch the ListView. ListView is the past. Use RecyclerView instead.
  2. add a RecyclerView.OnScrollListener to it, to get pixel-by-pixel scroll.
  3. use a Toolbar on your activity layout. So you can control the position of it.
  4. call setTranslationY(val) on your Toolbar to "scroll" it with the RecyclerView.

a few links with the docs for the mentioned classes:

  • http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html
  • https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
  • https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener.html
  • http://developer.android.com/reference/android/widget/Toolbar.html
  • https://developer.android.com/reference/android/view/View.html#setTranslationY(float)


回答2:

I created a solution based answer of @Budius and this link

First add this class

public class HidingRecyclerViewScrollListener extends RecyclerView.OnScrollListener {

    private final int UP = 0;
    private final int DOWN = 1;
    private final int margin = 5;
    private View mView;
    RecyclerView.LayoutManager mLayoutManager;

    private float currentPoint = 0;
    private int lastDirection = 1;

    public HidingRecyclerViewScrollListener(View view, LinearLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        mView = view;
    }

    public HidingRecyclerViewScrollListener(View view, GridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        mView = view;
    }

    public HidingRecyclerViewScrollListener(View view, StaggeredGridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        mView = view;
    }

    public int getFirstVisibleItem(int[] firstVisibleItemPositions) {
        int minSize = 0;
        for (int i = 0; i < firstVisibleItemPositions.length; i++) {
            if (i == 0) {
                minSize = firstVisibleItemPositions[i];
            } else if (firstVisibleItemPositions[i] < minSize) {
                minSize = firstVisibleItemPositions[i];
            }
        }
        return minSize;
    }


    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        float nextPoint = currentPoint + dy;


        if (nextPoint < 0) {
            nextPoint = 0;
        }


        if (nextPoint > viewSize()) {
            nextPoint = viewSize();
        }

        lastDirection = nextPoint >= currentPoint ? UP : DOWN;

        currentPoint = nextPoint;

        mView.setTranslationY(-currentPoint);
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            if (lastDirection == UP) {
                if (getFirstVisibleItem() > 0) {

                    currentPoint = viewSize();
                }
            }
            if (lastDirection == DOWN) {
                //Volta para origem
                currentPoint = 0;
            }
            mView.animate().translationY(-currentPoint);
        }
    }

    private int getFirstVisibleItem() {
        int firstVisibleItem = 0;
        if (mLayoutManager instanceof StaggeredGridLayoutManager) {
            int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(null);
            firstVisibleItem = getFirstVisibleItem(lastVisibleItemPositions);
        } else if (mLayoutManager instanceof LinearLayoutManager) {
            firstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
        } else if (mLayoutManager instanceof GridLayoutManager) {
            firstVisibleItem = ((GridLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
        }
        return firstVisibleItem;
    }

    private int viewSize() {
        return mView.getHeight() + margin;
    }
}

Is simple to use, only add using addOnScrollListener of your recyclerView

recyclerView = (RecyclerView) view.findViewById(R.id.mRecyclerView );
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.addOnScrollListener(new HidingRecyclerViewScrollListener(mView, layoutManager));
  • mView is the view you want to control

  • You can user this class with LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager (but i never test with GridLayoutManager)

In RecyclerView use the code below to the list does not stay below the object you want to control, this code is simpler and better to test, but use a Hearder in RecyclerView as is said in the link above has a better result.

android:clipToPadding="false"
android:paddingTop="@dimen/outher_view_dimem"

If you using SwipeRefreshLayout use code below to show ProgressBar

swipeRefreshLayout.setProgressViewOffset(true, 0, mViewHeight + actionBarHeight);