Android RecyclerView 使用大全 - 基础使用,item 动画,下拉刷新等

瀑布流也是个常用的显示控件了,但是在使用时经常遇到一些问题,比如滑动回顶部后出现空隙、item在滑动时乱跳等问题。

下面就来说说我怎么实现的瀑布流,并且怎么处理上面所说的这些问题的。

我使用了原生控件RecyclerView+StaggeredGridLayoutManager来实现的瀑布流,没有用第三方开源框架。下面以2列的瀑布流为例子开始讲解。

因为使用了StaggeredGridLayoutManager实现瀑布流,但是在设置后发现图片在滑动加载过程中高度会发生变化,在网上搜索了很多资料后,总结解决办法是在onBindViewHolder中绑定View时,给ImageView设置宽高,就能解决这个问题。

先看一下最终实现效果:

正常显示的瀑布流.gif

提前说明下,我使用的是Glide3,读者们可以自行修改为Glide4。

1.实现瀑布流

先说说实现思路:

  • 写布局文件,分别有2个布局文件,Activity的布局文件和Adapter的布局文件
  • 写适配器,瀑布流的适配器里需要设置ImageView的宽高。
  • 写RecyclerView,给RecyclerView设置StaggeredGridLayoutManager并设置适配器。
  • 添加数据测试效果,根据效果反馈进行修改

第一步:写布局文件

Activity的布局文件只有一个RecyclerView就不贴了,贴一下Adapter的布局文件:

adapter_item_card.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/card"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:background="@android:color/holo_green_dark"android:orientation="vertical"><ImageViewandroid:id="@+id/card_image"android:layout_width="match_parent"android:layout_height="wrap_content"tools:src="@mipmap/ic_launcher" /><TextViewandroid:id="@+id/card_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="8dp"android:layout_marginBottom="2dp"tools:text="hello" />
</LinearLayout>

第二步:写适配器

适配器中包含数据Card的集合,Card类包含如下几个属性:

    private String title;private String img_url;private int width;private int height;

在适配器中主要就是将数据绑定到view上,最关键的步骤是根据图片的宽高算出图片的宽高比,然后根据宽高比选择正方形显示,还是长方形显示,最后通过setLayoutParams方法来设置图片的宽高。

思路如下:

  • 计算图片宽度
  • 根据图片宽高比,确定图片使用正方形或是4比3的长方形显示
  • 使用setLayoutParams方法设置图片宽高
  • 使用Glide加载图片并用override重写图片宽高

适配器核心代码如下:

private final double STANDARD_SCALE = 1.1; //当图片宽高比例大于STANDARD_SCALE时,采用3:4比例,小于时,则采用1:1比例
private final float SCALE = 4 * 1.0f / 3;       //图片缩放比例
private List<Card> cards = new ArrayList<>();@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {Card card = mCards.get(position);setCardView(holder, card);
}private void setCardView(ViewHolder holder, Card card) {//计算图片宽高LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.image.getLayoutParams();//2列的瀑布流,屏幕宽度减去两列间的间距space所的值再除以2,计算出单列的imageview的宽度,space的值在RecyclerView初始化时传入float itemWidth = (ScreenUtil.getScreenWidth(context) - space) / 2;layoutParams.width = (int) itemWidth;float width = card.getWidth();float height = card.getHeight();float scale = height / width;if (scale > STANDARD_SCALE) {//采用3:4显示layoutParams.height = (int) (itemWidth * SCALE);} else {//采用1:1显示layoutParams.height = (int) itemWidth;}holder.image.setLayoutParams(layoutParams);Glide.with(context).load(card.getImg_url()).asBitmap().placeholder(R.mipmap.ic_launcher).diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().into(holder.image);holder.title.setText(card.getTitle());
}

写好适配器后,就可以在MAinActivity中初始化RecyclerView和适配器了,代码如下:

        int space = 20;StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
//        layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);   //设置后瀑布流不显示了mRecyclerView.setLayoutManager(layoutManager);mRecyclerView.setItemAnimator(null);mRecyclerView.addItemDecoration(new StaggeredItemDecoration(space));//单位pxmAdapter = new StaggeredGridAdapter(space);mAdapter.setCards(mCards);mRecyclerView.setAdapter(mAdapter);

在网上看到使用StaggeredGridLayoutManager的setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE)设置来处理瀑布流滑动到顶部空白的问题,结果发现添加这句代码后,整个瀑布流都不显示了,所以不能这样处理。

在上面的代码中我设置了space值,space是指两列卡片之间的距离,根据需求设置,这里space用在了2个地方分别是:

mRecyclerView.addItemDecoration(new StaggeredItemDecoration(space));
mAdapter = new StaggeredGridAdapter(space);

前者用于设置两列瀑布流之间的距离,后者是用来计算单列图片的宽度。StaggeredItemDecoration类的代码在此。

代码写好后,来看看瀑布流效果。

好像有点奇怪的地方,在滑动过程中前面图片1、2、3的大小发生了变化。我当时也是很疑惑,在网上搜索图片大小改变的问题原因也没有找到,好像与RecyclerView的图片缓存机制有关,有知道的胖友可以告知一下。

最后通过在Glide加载图片时添加override设置图片宽高解决了,关于override设置图片可以看看这篇文章《Glide的override方法和View的setLayoutParams方法设置图片宽高对比》。

Glide.with(context).load(card.getImg_url()).asBitmap().placeholder(R.mipmap.ic_launcher).diskCacheStrategy(DiskCacheStrategy.RESULT).override(layoutParams.width, layoutParams.height).centerCrop().into(holder.image);

解决后的效果如下,可以看到在滑动过程中,图片大小没有再变化:

正常显示的瀑布流.gif

2. 瀑布流顶部出现空隙、item乱跳等问题

照上面的处理已经能解决顶部出现空隙、item乱跳的问题,但是建议在瀑布流更新时采用notifyItemRangeInserted()方法更新,可以避免一些不必要的问题。

if (FIRST_PAGE_LAST_ID.equals(lastId)) {mAdapter.notifyDataSetChanged();//第一页更新
} else {mAdapter.notifyItemRangeInserted(startPosition, count);//第一页以外使用notifyItemRangeInserted()更新
}

如果对你有帮助的话,点赞、评论、赞赏都是对我的鼓励,也是支持我写下去的动力,谢谢!

Android RecyclerView 实现瀑布流相关推荐

  1. android 水平方向瀑布流,Android RecyclerView(瀑布流)水平/垂直方向分割线

     Android RecyclerView(瀑布流)水平/垂直方向分割线 Android RecyclerView不像过去的ListView那样随意的设置水平方向的分割线,如果要实现Recycle ...

  2. Android RecyclerView实现瀑布流,图片自适应高度,不闪烁,解决位置交换

    记录一下以前自己代码中用到过代码效果,也做个备份,省的以后代码找不到,大家也可以参考参考,也许看过网上某些笔记,但是不记得了链接了,有问题可以联系本人 以下会写从布局到java代码以及用到的工具类都写 ...

  3. SwipeRefreshLayout+CardView+RecyclerView 精美瀑布流效果

    博主声明: 转载请在开头附加本文链接及作者信息,并标记为转载.本文由博主 威威喵 原创,请多支持与指教. 本文首发于此   博主:威威喵  |  博客主页:https://blog.csdn.net/ ...

  4. RecyclerView实现瀑布流,图片自适应高度

    话不多说,先上效果图 对于RecyclerView,相信大家都不陌生了,这个集listView,GridView,瀑布流效果与一身强大控件,渐渐地渗透在每个App.... 还是回到正题,如何让Recy ...

  5. 【RecyclerView】 五、RecyclerView 布局 ( 瀑布流 | 交错网格局管理器 StaggeredGridLayoutManager )

    文章目录 一.交错网格局管理器 StaggeredGridLayoutManager ( 瀑布流 ) 二.交错网格局管理器默认设置 三.交错网格局管理器水平方向设置 四.完整代码示例 五.Recycl ...

  6. 友盟登陆传值+OkHttp+recyclerview展示瀑布流+跳转Intent传值+属性动画

    友盟详情见 https://blog.csdn.net/aijaijgnaw/article/details/84203936 分包 友盟第三方登录 MyApp(Application) packag ...

  7. 使用RecyclerView实现瀑布流

    准备工作 添加网络权限,在此项目中用于获取网络图片 添加Glide依赖,用于加载图片 启用dataBinding,也可不用dataBinding,这里主要是练习一下 implementation 'c ...

  8. RecyclerView StaggeredGridLayoutManager瀑布流实现中遇到的问题

    1.下面的代码主要是用于布局错乱后,自动修复,以及防止item左右交换的问题.在我遇到的问题当中,如果只setGapStrategy,会导致列表往回滑动时,顶部出现空白的问题.所以需要开启系统自动计算 ...

  9. 使用RecyclerView实现瀑布流,仿照小红书,解决顶部留白、卡顿等问题

    一.最终效果: 二.工程结构框架: 三.核心实现: (1).实现RecyclerView控件的适配器类 主要就是实现下面三个函数的重载: @NonNull@Overridepublic Recycle ...

最新文章

  1. mysql80连接不上本地服务器_Windows Server 2016 远程桌面本地连接不上
  2. oracle12c asmfd,Oracle 12C R2-新特性-自动配置ASMFD
  3. python那些事儿编程技巧_python一些编程技巧(持续更新)
  4. 重新下载python以前下的包还用重新安装吗_强制“pip”在切换到其他Python二进制文件后重新编译以前安装的包(numpy)...
  5. android输入自动补全,Android用户输入自动提示控件AutoCompleteTextView使用方法
  6. django 1.8 官方文档翻译:7-2 管理操作
  7. Windows 11 高门槛“吓退”用户,Linux 成“香饽饽”?
  8. paip.python优缺点attilax总结
  9. 攻略AI面试官的N种姿势
  10. 使用HLS协议连接nginx实现近实时流方式播放视频
  11. ngx-bootstrap学习笔记
  12. wps图片与图片间距怎么调整_wps图片与图片间距怎么调整_微信图文排版,字间距,行间距,怎么调整合适?......
  13. 希尔伯特及其《几何学基础》电子版(英文PDF),
  14. 疫情面试了13家企业软件测试岗位,面试题整理
  15. 线下停摆,线上狂欢,疫情下“云健身”火了!
  16. 全文搜索,迅搜(Xunsearch)使用心得
  17. Linux下使用hiredis库与libevent实现异步接口的I/O复用
  18. 频繁跳槽写入简历的三条原则!
  19. simcom工作记录
  20. Windows窃取U盘数据

热门文章

  1. 2019秋招求职攻略
  2. W7下安装VS2017版本相关问题
  3. 爱因斯坦计划最新进展(201710)
  4. rocketmq的broker源码解读五(刷盘)
  5. X61 U盘安装系统
  6. 防水运动耳机排行榜、防水防汗的运动耳机介绍
  7. 使用SharePoint Designer定制开发专家库系统实例!
  8. java游戏 火车轨道,火车轨道施工模拟器
  9. java+语音识别+谷歌,谷歌语音识别(Android)崩溃
  10. postgre——case、union、小计总计(GROUP BY ROLLUP)写法