CoordinatorLayout: Hiding/Showing half visible toolbar?

倾然丶 夕夏残阳落幕 提交于 2019-12-03 03:21:34

问题


Id like to achieve a similar effect as the one you can see in Google Play store, where by scrolling the content the Toolbar goes off-screen as you scroll.

This works fine with the CoordinatorLayout (1) introduced at #io15, however: If you stop the scroll "mid-way" the Toolbar remains on screen, but is cut in half: I want it to animate off-screen, just like in the Google Play store. How can I achieve that?


回答1:


Now the Android Support Library 23.1.0 has a new scroll flag SCROLL_FLAG_SNAP which allows you to achieve this effect.

AppBarLayout supports a number of scroll flags which affect how children views react to scrolling (e.g. scrolling off the screen). New to this release is SCROLL_FLAG_SNAP, ensuring that when scrolling ends, the view is not left partially visible. Instead, it will be scrolled to its nearest edge, making fully visible or scrolled completely off the screen.




回答2:


Activity Layout file :

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="?attr/actionBarSize"
        android:clipToPadding="false"/>

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>

</FrameLayout>

Now inside the activity, setup Toolbar and RecyclerView. Assign OnScrollListener to RecyclerView

 recyclerView.setOnScrollListener(new MyScrollListener(this));

Extend MyScrollListerner from RecyclerView.OnScrollListener.

public abstract class MyScrollListener extends RecyclerView.OnScrollListener {

    private static final float TOOLBAR_HIDE_THRESHOLD = 10;
    private static final float TOOLBAR_SHOW_THRESHOLD = 70;

    private int mToolbarOffset = 0;
    private boolean mControlsVisible = true;
    private int mToolbarHeight;
    private int mTotalScrolledDistance;

    public MyScrollListener(Context context) {

        final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
                new int[]{R.attr.actionBarSize});
        mToolbarHeight = (int) styledAttributes.getDimension(0, 0);
        styledAttributes.recycle();

        return toolbarHeight;
        mToolbarHeight = Utils.getToolbarHeight(context);
    }

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

        if(newState == RecyclerView.SCROLL_STATE_IDLE) {
            if(mTotalScrolledDistance < mToolbarHeight) {
                setVisible();
            } else {
                if (mControlsVisible) {
                    if (mToolbarOffset > TOOLBAR_HIDE_THRESHOLD) {
                        setInvisible();
                    } else {
                       setVisible();
                    }
                } else {
                    if ((mToolbarHeight - mToolbarOffset) > TOOLBAR_SHOW_THRESHOLD) {
                        setVisible();
                    } else {
                        setInvisible();
                    }
                }
            }
        }
    }

        @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        clipToolbarOffset();
        onMoved(mToolbarOffset);

        if((mToolbarOffset <mToolbarHeight && dy>0) || (mToolbarOffset >0 && dy<0)) {
            mToolbarOffset += dy;
        }
        if (mTotalScrolledDistance < 0) {
            mTotalScrolledDistance = 0;
        } else {
            mTotalScrolledDistance += dy;
        }
    }

    private void clipToolbarOffset() {
     if(mToolbarOffset > mToolbarHeight) {
         mToolbarOffset = mToolbarHeight;
       } else if(mToolbarOffset < 0) {
            mToolbarOffset = 0;
        }
    }

    private void setVisible() {
        if(mToolbarOffset > 0) {
            onShow();
            mToolbarOffset = 0;
        }
        mControlsVisible = true;
    }

    private void setInvisible() {
        if(mToolbarOffset < mToolbarHeight) {
            onHide();
            mToolbarOffset = mToolbarHeight;
        }
        mControlsVisible = false;
    }

    public abstract void onMoved(int distance);
    public abstract void onShow();
    public abstract void onHide();
}



回答3:


Overriding the AppBarLayout seems to be a better solution, as there are two possible scroll-events - of the entire CoordinatorLayout, and of the RecyclerView/NestedScrollView

See this answer as a possible working code: https://stackoverflow.com/a/32110089/819355



来源:https://stackoverflow.com/questions/30575293/coordinatorlayout-hiding-showing-half-visible-toolbar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!