CoordinatorLayout:如何隐藏/显示仅部分可见的工具栏?

10

我希望能够达到与Google Play商店相似的效果,即当您滚动内容时,工具栏(Toolbar)会随着滚动而从屏幕上消失。

使用在#io15中引入的CoordinatorLayout(1)可以很好地实现此目标,但是:如果您在滚动过程中停止滚动,则工具栏仍将保留在屏幕上,但被裁剪了一半:我想要它像在Google Play商店中那样自动滑出屏幕。我该如何实现这个效果?

3个回答

4
现在Android Support Library 23.1.0新增了一个名为SCROLL_FLAG_SNAP的滚动标记,用于实现此效果。

AppBarLayout支持多种滚动标记,影响子控件在滚动时的反应(例如,滚动至屏幕外)。此版本新增了SCROLL_FLAG_SNAP,确保当滚动结束时,视图不会部分可见。相反,它将滚动到最近的边缘,使其完全可见或完全滚出屏幕。


1

活动布局文件:

<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>

现在,在活动中设置工具栏和RecyclerView。 将OnScrollListener分配给RecyclerView。
 recyclerView.setOnScrollListener(new MyScrollListener(this));

将 MyScrollListerner 从 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();
}

@zoltish 如果这对您有用,请告诉我并接受它作为答案。 :) - nishantapatil
应用栏/工具栏可以滚动而不会滚动RecyclerView,这种情况下监听器代码不会被触发。当RecyclerView在顶部且没有可向上滚动的内容时,用户向下拉动屏幕会导致整个CoordinatorLayout滚动。 - marmor

0

覆盖AppBarLayout似乎是更好的解决方案,因为有两种可能的滚动事件 - 整个CoordinatorLayout的滚动事件和RecyclerView / NestedScrollView的滚动事件

可以参考此答案作为可能的工作代码: https://dev59.com/pFwZ5IYBdhLWcg3wG9F_#32110089


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接