Android 聊天视图的可伸缩或折叠工具栏

Android retractable or collapsed toolbar for chat view

我正在为聊天视图使用折叠的工具栏,一切正常

app:layout_behavior="@string/appbar_scrolling_view_behavior"

在我的回收者看来

app:layout_scrollFlags="scroll|enterAlways|snap"

关于伸缩header

我将它用于聊天视图,因此由于

,recyclerView 中的第一个元素位于列表底部
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setReverseLayout(true);

问题是我想在向上滚动时隐藏 header 并在向下滚动时隐藏它,这与实际行为完全相反。当我到达列表顶部时 header 出现,(最旧的消息)相反,当我显示最新消息

到达底部时,我想让它可见

我找到了一个解决方案,我将旧方法与 OnScrollListener 一起用于可伸缩 header 并将其反转以适合反向布局管理器

public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {

private static final float HIDE_THRESHOLD = 10;
private static final float SHOW_THRESHOLD = 70;

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

public HidingScrollListener(int mToolbarHeight) {
    this.mToolbarHeight = mToolbarHeight;
}

@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 > HIDE_THRESHOLD) {
                    setInvisible();
                } else {
                    setVisible();
                }
            } else {
                if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
                    setVisible();
                } else {
                    setInvisible();
                }
            }
        }
    }
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    dy = dy * -1;
    clipToolbarOffset();
    onMoved(mToolbarOffset);
    if ((mToolbarOffset < mToolbarHeight && dy > 0) || (mToolbarOffset > 0 && dy < 0)) {
        mToolbarOffset += dy;
    }
    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();
}

然后我在我的片段中像这样使用它

  dataBinding.chatDetailRoot.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mToolbarHeight = dataBinding.chatDetailAdsHeader.getHeight();
            dataBinding.chatDetailRecyclerView.addOnScrollListener(new HidingScrollListener(mToolbarHeight) {
                @Override
                public void onMoved(int distance) {
                    dataBinding.chatDetailAdsHeader.setTranslationY(-distance);
                }

                @Override
                public void onShow() {
                    dataBinding.chatDetailAdsHeader.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
                }

                @Override
                public void onHide() {
                    dataBinding.chatDetailAdsHeader.animate().translationY(-mToolbarHeight).setInterpolator(new AccelerateInterpolator(2)).start();
                }
            });
            dataBinding.chatDetailRoot.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });
}

我正在使用 viewTreeObserver,因为我需要获取工具栏高度并且 chatDetailAdsHeader 是我的 AppBarLayout 组件