Recycleview实现复杂页面 三种以上布局 瀑布流 多布局 scrollview嵌套recyclerView 显示不全 滑动冲突 之进阶终极篇

 *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布   

 相信很多安卓开发的朋友,尤其是刚从事安卓开发的朋友, 当产品经理递过来一张复杂页面的设计图时 , 都会有一种茫然的感觉 , 在心里想着如何实现 , 然后网上搜索如何实现复杂布局页面,当初我也是这么过来的, 可以说踩了很多很大的坑 ,  所以决定写下这篇博客 ,  供各位猿猿参观 , 想相信看完此篇 , 绝对是最后一篇 ,  不用再找了 , 当然 此篇为进阶篇 。 如果你对recycleview 还不熟悉 , 建议先了解recycleview , 熟悉其基本使用。如果有问题 , 欢迎加QQ群 661614986。

言归正传, 先来看一下效果图:





 gif录出来 有点怪 , 所以就截图了,源码已放入github

点击打开链接


下面我来分析一下这种复杂界面的具体实现思路, 当然这里非常感谢 奋斗  liaoinstan 大神的文章 http://blog.csdn.net/liaoinstan/article/details/52671101,朋友可以看一下 , 最初我也是看了此篇 , 但是此篇并非完美, 在此我进一步总结一下 。

 

首先我们来做一个分水岭, 就是布局中上拉加载的布局是否是瀑布流,


1、如果不是瀑布流, 那就很简单了,借鉴一下liaoinstan的图片,


如果实现此图, liaoinstan给了如下两种方案,

第一种:

 这里recycleview5 应该还是列表管理器, 懒得画图了,意思一样 。

这种方案构思就是recycleview里面嵌套多recycleview,构思简单,编写也是行如流水,能够实现需求,但是问题来了,以下是重点,这种多嵌套的写法,在上拉加载的时候,拉到后面基本就会很卡,就算释放glide(或者其他图片加载框架)的内存也是释放不掉,直至oom或者卡死不动,所以这种嵌套思路只适合没有加载更多的的情况。

第二种:


这中思路里面最重要的方法就是

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int type = getItemViewType(position);
                    switch (type){
                        case TYPE_SLIDER:
                        case TYPE_TYPE2_HEAD:
                        case TYPE_TYPE3_HEAD:
                            return 6;
                        case TYPE_TYPE2:
                            return 3;
                        case TYPE_TYPE3:
                            return 2;
                        default:
                            return 3;
                    }
                }
            });
        }
    }
liaoinstan大神已经给了具体代码和思路,完美实现功能,非常感谢。


2.如果需求是带瀑布流的

那么,第一种情况里面的 onAttachedToRecyclerView方法瀑布流管理器里面就不存在,因此无法使用,只能另寻他法,liaoinstan大神推荐TwowayView能实现上图这种效果但是, 呵呵,不好意思,当你用TwowayView写实际应用时, 需要网络加载时, 问题出现了,那就是你来回下拉刷新几次,布局上面就会有一块白的空白区域, 直至最后你的布局完全看不见, 只剩下一片白 ,我没有解决此问题。当时我写我们公司的应用时, 写到这里的时候,我就一脸懵逼了, 然后就用最最古老的办法,直接scrollview里面嵌套几个recycleview,写到最后还是意料之中出现问题了,上拉加载到最后还是会卡顿,而且在6.0以上 高度总是有问题。
到这里,大哭大哭大哭我差点想和产品说我们不用瀑布流好不好,但我又从新搜了一下,在瀑布流管理器里面有LayoutParams.setFullSpan(true);方法,在 

onCreateViewHolder(ViewGroup parent, int viewType)

 总体思路就是,把下面的瀑布流部分作为一种type,其他无需加载更多的布局放在recycleview里面

使用此方法使这一行占满全屏,这是我到现在总结出来的最好实现方式。

思路图如下:


 部分代码如下

  @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_TOP) {
               //头部轮播图
            View viewtop = inflater.inflate(R.layout.adapter_slider, parent, false);
            StaggeredGridLayoutManager.LayoutParams params =
                    (StaggeredGridLayoutManager.LayoutParams) viewtop.getLayoutParams();
            params.setFullSpan(true);//最为重要的一个方法,占满全屏,以下同理
            viewtop.setLayoutParams(params);
            return new TypeTopsliderHolder(viewtop);
        } else if (viewType == TYPE_HEADER) {

            View view2 = inflater.inflate(R.layout.item_homepagertypeheader_type, parent, false);

            StaggeredGridLayoutManager.LayoutParams params =
                    (StaggeredGridLayoutManager.LayoutParams) view2.getLayoutParams();
            params.setFullSpan(true);
            view2.setLayoutParams(params);
            return new TypeheadHolder(view2);
        } else if (viewType == TYPE_CENTER) {
            //中间head下面的布局
            View view = inflater.inflate(R.layout.itam_homepageradapter_rv2, parent, false);
            StaggeredGridLayoutManager.LayoutParams params2 =
                    (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
            params2.setFullSpan(true);
            view.setLayoutParams(params2);
            return new TypetypeHolder2(view);

        } else if (viewType == TYPE_CATEGORY) {
//四个快速入口的holder
//这里的TypetypeHolder和上面的TypetypeHolder2 其实可以写成一个holder,这里为了简单,避免引起复用带来的问题,分开了
            View view = inflater.inflate(R.layout.itam_homepageradapter_rv2, parent, false);
            StaggeredGridLayoutManager.LayoutParams params2 =
                    (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
            params2.setFullSpan(true);
            view.setLayoutParams(params2);
            return new TypetypeHolder(view);

        } else if (viewType == TYPE_REFRESH) {
            return new TypeRefresh(inflater.inflate(R.layout.item_raiders2, parent, false));
        } else {

            View viewtop = inflater.inflate(R.layout.adapter_slider, parent, false);
            StaggeredGridLayoutManager.LayoutParams params =
                    (StaggeredGridLayoutManager.LayoutParams) viewtop.getLayoutParams();
            params.setFullSpan(true);
            viewtop.setLayoutParams(params);
            return new TypeTopsliderHolder(viewtop);
        }
    }



这个方法 在大神的文章里 只是 副作用的 提了一下, 光想着TwowayView 了 所以没在意 ,最后还是此方法解决了这种需求。


我的线上项目为[空艺术,朋友可以点击下载看一下效果](http://a.app.qq.com/o/simple.jsp?pkgname=com.happyo2o.artexhibition),首页就是这个原理实现的,大家可以看一下效果。


总结:本人只是理论性的总结了复杂布局的实现方式,以及一些坑 , 避免各位浪费时间和精力 ,鄙人在此献丑了,代码已经全部上传,github项目源码 欢迎star , 转载  , 万分感谢 。 



  • 18
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 32
    评论
如果您想在RecyclerView的FlexBoxLayoutManager布局实现当行数超出一行时显示省略按钮的效果,可以通过以下步骤来实现: 1. 首先,定义一个自定义的FlexBoxLayoutManager,用于监听RecyclerView的滚动事件。 ```java public class CustomFlexBoxLayoutManager extends FlexboxLayoutManager { private boolean isNeedEllipsis = false; public CustomFlexBoxLayoutManager(Context context) { super(context); } public CustomFlexBoxLayoutManager(Context context, int flexDirection) { super(context, flexDirection); } public CustomFlexBoxLayoutManager(Context context, int flexDirection, int flexWrap) { super(context, flexDirection, flexWrap); } @Override public void onLayoutCompleted(RecyclerView.State state) { super.onLayoutCompleted(state); checkIfNeedEllipsis(); } @Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); checkIfNeedEllipsis(); } private void checkIfNeedEllipsis() { int totalWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int totalHeight = getHeight() - getPaddingTop() - getPaddingBottom(); int lineWidth = 0; int lineHeight = 0; int lineCount = 1; isNeedEllipsis = false; for (int i = 0; i < getItemCount(); i++) { View view = findViewByPosition(i); if (view != null) { int width = getDecoratedMeasuredWidth(view); int height = getDecoratedMeasuredHeight(view); if (lineWidth + width > totalWidth) { lineWidth = width; lineHeight = height; lineCount++; if (lineCount > 1) { isNeedEllipsis = true; break; } } else { lineWidth += width; lineHeight = Math.max(lineHeight, height); } } } if (isNeedEllipsis) { // 当超出一行时,显示省略按钮 // TODO: 显示省略按钮 } else { // 当不超出一行时,隐藏省略按钮 // TODO: 隐藏省略按钮 } } public boolean isNeedEllipsis() { return isNeedEllipsis; } } ``` 2. 在RecyclerView中设置自定义的FlexBoxLayoutManager,并设置一个监听器来监听省略按钮的点击事件。 ```java RecyclerView recyclerView = findViewById(R.id.recyclerView); CustomFlexBoxLayoutManager layoutManager = new CustomFlexBoxLayoutManager(this); recyclerView.setLayoutManager(layoutManager); layoutManager.setOnEllipsisButtonClickListener(new OnEllipsisButtonClickListener() { @Override public void onEllipsisButtonClick() { // 处理省略按钮的点击事件 // TODO: 处理省略按钮的点击事件 } }); ``` 3. 在CustomFlexBoxLayoutManager的checkIfNeedEllipsis()方法中,通过遍历所有的item来计算当前行数,判断当前行数是否超出一行。如果超出,则显示省略按钮,否则隐藏省略按钮。在显示省略按钮时,您可以使用PopupWindow或者Dialog等方式来实现。在隐藏省略按钮时,需要将省略按钮隐藏掉,以免影响用户体验。 4. 最后,您还可以通过设置RecyclerView的padding来控制省略按钮的显示位置。在显示省略按钮时,您可以将省略按钮添加到RecyclerView的父布局中,以便在滚动RecyclerView时不会被遮挡。 ```java recyclerView.setPadding(0, 0, ellipsisButtonWidth, 0); ``` 其中,ellipsisButtonWidth是省略按钮的宽度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值