如何在RecyclerView中实现粘性页脚 [英] How implement sticky footer in recyclerview

查看:100
本文介绍了如何在RecyclerView中实现粘性页脚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有RecyclerView,我需要下一个行为:

I have RecyclerView and I need next behavior:

  • 如果有很多项目(更多则适合屏幕)-页脚是最后一个项目
  • 如果没有项目/没有项目-页脚位于屏幕底部

请告知我如何实现此行为.

Please advise how can I implement this behavior.

推荐答案

您可以使用RecyclerView.ItemDecoration来实现此行为.

You can use RecyclerView.ItemDecoration to implement this behavior.

public class StickyFooterItemDecoration extends RecyclerView.ItemDecoration {

    /**
     * Top offset to completely hide footer from the screen and therefore avoid noticeable blink during changing position of the footer.
     */
    private static final int OFF_SCREEN_OFFSET = 5000;

    @Override
    public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent, RecyclerView.State state) {
        int adapterItemCount = parent.getAdapter().getItemCount();
        if (isFooter(parent, view, adapterItemCount)) {
            //For the first time, each view doesn't contain any parameters related to its size,
            //hence we can't calculate the appropriate offset.
            //In this case, set a big top offset and notify adapter to update footer one more time.
            //Also, we shouldn't do it if footer became visible after scrolling.
            if (view.getHeight() == 0 && state.didStructureChange()) {
                hideFooterAndUpdate(outRect, view, parent);
            } else {
                outRect.set(0, calculateTopOffset(parent, view, adapterItemCount), 0, 0);
            }
        }
    }

    private void hideFooterAndUpdate(Rect outRect, final View footerView, final RecyclerView parent) {
        outRect.set(0, OFF_SCREEN_OFFSET, 0, 0);
        footerView.post(new Runnable() {
            @Override
            public void run() {
                parent.getAdapter().notifyDataSetChanged();
            }
        });
    }

    private int calculateTopOffset(RecyclerView parent, View footerView, int itemCount) {
        int topOffset = parent.getHeight() - visibleChildsHeightWithFooter(parent, footerView, itemCount);
        return topOffset < 0 ? 0 : topOffset;
    }

    private int visibleChildsHeightWithFooter(RecyclerView parent, View footerView, int itemCount) {
        int totalHeight = 0;
        //In the case of dynamic content when adding or removing are possible itemCount from the adapter is reliable,
        //but when the screen can fit fewer items than in adapter, getChildCount() from RecyclerView should be used.
        int onScreenItemCount = Math.min(parent.getChildCount(), itemCount);
        for (int i = 0; i < onScreenItemCount - 1; i++) {
            totalHeight += parent.getChildAt(i).getHeight();
        }
        return totalHeight + footerView.getHeight();
    }

    private boolean isFooter(RecyclerView parent, View view, int itemCount) {
        return parent.getChildAdapterPosition(view) == itemCount - 1;
    }
}

请确保为RecyclerView高度设置 match_parent .

Make sure to set match_parent for the RecyclerView height.

请查看示例应用程序 https://github.com/JohnKuper/recyclerview-粘性页脚及其工作方式 http://sendvid.com/nbpj0806

Please have a look at the sample application https://github.com/JohnKuper/recyclerview-sticky-footer and how it works http://sendvid.com/nbpj0806

该解决方案的一个巨大缺点是,只有在整个应用程序中(而不是在修饰中)notifyDataSetChanged()之后,它才能正常工作.有了更具体的通知,它将无法正常工作并无法支持它们,因此需要一种更多的逻辑方法.此外,您还可以通过 eowise 从库 recyclerview-stickyheaders 中获取见解,并改进此解决方案.

A Huge drawback of this solution is it works correctly only after notifyDataSetChanged() throughout an application(not inside decoration). With more specific notifications it won't work properly and to support them, it requires a way more logic. Also, you can get insights from the library recyclerview-stickyheaders by eowise and improve this solution.

这篇关于如何在RecyclerView中实现粘性页脚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆