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"> <ImageView android:id="@+id/card_image" android:layout_width="match_parent" android:layout_height="wrap_content" tools:src="@mipmap/ic_launcher" /> <TextView android: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<>();@Overridepublic 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));//单位px mAdapter = 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()更新}
如果对你有帮忙的话,点赞、评论、赞叹都是对我的激励,也是反对我写下去的能源,谢谢!