原文链接:点击打开链接
===============================================================================================
相信很多安卓开发的朋友,尤其是刚从事安卓开发的朋友, 当产品经理递过来一张复杂页面的设计图时 , 都会有一种茫然的感觉 , 在心里想着如何实现 , 然后网上搜索如何实现复杂布局页面,当初我也是这么过来的, 可以说踩了很多很大的坑 , 所以决定写下这篇博客 , 供各位猿猿参观 , 想相信看完此篇 , 绝对是最后一篇 , 不用再找了 , 当然 此篇为进阶篇 。 如果你对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;
- }
- }
- });
- }
- }
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 , 转载 , 万分感谢 。