使用RecyclerView和Glide实现图片瀑布流(防止错位)
来源:互联网 发布:bp算法的基本思想 编辑:程序博客网 时间:2024/06/05 14:32
使用RecyclerView和Glide实现图片瀑布流(防止错位)
最近正在学习Android的新控件RecyclerView,感觉这是一个自由度很高的控件,除了可以实现最基本的ListView,GridView的功能之外,还可以实现瀑布流的效果。 Android RecyclerView 使用完全解析 体验艺术般的控件,其中很详细的说明了如何去使用和订制RecyclerView,而这篇博客写的是我在使用RecyclerView与Glide实现瀑布流功能时遇到的坑。
首先贴出activity,布局代码
public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private List<String> mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); } private void initData() { mDatas = new ArrayList<String>(); for (int i = 0 ; i < Images.imageUrls.length ; i++){ String data = Images.imageUrls[i]; mDatas.add(data); } } private void initView() { recyclerView = (RecyclerView) findViewById(R.id.rv); //添加布局管理 StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(manager); //设置适配器 recyclerView.setAdapter(new RecycleAdapter(this,mDatas)); //设置item添加和删除的动画// recyclerView.setItemAnimator(); //设置分隔线// recyclerView.addItemDecoration(new DividerGridItemDecoration(this)); }}
<?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:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.syf.recyclerview.MainActivity"><android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></LinearLayout>
activity的布局很简单,其中只有一个recyclerview,activiy中的代码也是最基本的加载recyclerview的代码。
然后是adapter的代码
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.MyViewHolder> { private List<String> mDatas; private Context context; private LayoutInflater inflater; private SparseArray<Integer> heightArray; public RecycleAdapter(Context context , List<String> mDatas){ this.context = context; this.mDatas = mDatas; this.inflater = LayoutInflater.from(context); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { heightArray = new SparseArray<Integer>(); View itemView = inflater.inflate(R.layout.item_recycle,parent,false); MyViewHolder viewHolder = new MyViewHolder(itemView); return viewHolder; } @Override public void onBindViewHolder(final MyViewHolder holder, final int position) { Glide.with(context) .load(mDatas.get(position)) .into(holder.iv); } @Override public int getItemCount() { return mDatas.size(); } class MyViewHolder extends RecyclerView.ViewHolder{ ImageView iv; public MyViewHolder(View itemView) { super(itemView); iv = (ImageView) itemView.findViewById(R.id.iv); } }}
adapter中在onBindViewHolder中使用了Glide图片框架来加载图片。这样子一个最基本的瀑布流加载图片就实现了。但是这样加载出来的瀑布流在滑动的时候是会有图片的错位的。为了解决这个问题,需要如下几个步骤:
1.在activity中加入manager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);这句代码,可以防止recyclerview在加载的过程中的item的错位。但是,加入了这句代码后,recyclerview的图片加载问题反而更大了,有时甚至会出现大片的空白,就像下图所示:
卧槽,那加这句代码干什么,还不如不加呢。先不要急,这句代码是防止item错位和位置变化的,但是图片在一开始设置的高度是wrap_content,有些图片加载的快,把位置已经占好了,然后随着用户手指的滑动,有些图片还没有加载出来,但是界面已经滑动到更下面了,这些图片没有加载出来,所以导致这样的结果。要解决这样的问题其实也简单,只要在图片加载之前去获取图片的高度,并将ImageView的高度设置好,就能解决这个问题了。
2在adapter中的onBindViewHolder中获取图片的高度,并设置,进行占位代码如下
Glide.with(context) .load(mDatas.get(position)) .asBitmap() .placeholder(R.mipmap.ic_launcher) .into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) { // Do something with bitmap here. int height = bitmap.getHeight(); //获取bitmap信息,可赋值给外部变量操作,也可在此时行操作。 bitmap.getWidth(); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.iv.getLayoutParams(); layoutParams.height = height; holder.iv.setLayoutParams(layoutParams); } });
这里使用了glide中的SimpleTarget,当资源准备完毕时,可以获取图片的高度,并设置成ImgaeView的高度。但是,如果每次滑动都要去重新获取,这样消耗资源也是很大的。所以在获取的同时,将图片的高度值存储在SpareArray中,这样下次加载时,就可以使用SpareArray中存储的图片的高度值了。所以onBindViewHolder中的代码应该这样写:
if (heightArray.get(position) == null){ Glide.with(context) .load(mDatas.get(position)) .asBitmap() .placeholder(R.mipmap.ic_launcher) .into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) { // Do something with bitmap here. int height = bitmap.getHeight(); //获取bitmap信息,可赋值给外部变量操作,也可在此时行操作。 bitmap.getWidth(); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.iv.getLayoutParams(); layoutParams.height = height; holder.iv.setLayoutParams(layoutParams); heightArray.put(position,height); } }); }else { int height = heightArray.get(position); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.iv.getLayoutParams(); layoutParams.height = height; holder.iv.setLayoutParams(layoutParams); } Glide.with(context) .load(mDatas.get(position)) .into(holder.iv);
这样就可以解决recyclerview中的图片滑动加载图片错位的问题了。
- 使用RecyclerView和Glide实现图片瀑布流(防止错位)
- RecyclerView实现图片瀑布流
- 用Glide去实现图片的缓存和瀑布流
- 使用StaggeredGridLayoutManager瀑布流,Glide显示图片
- 手把手教你做开源项目MyMeiZi 二(使用RecyclerView+Glide打造瀑布流)
- RecyclerView实现瀑布流,图片自适应高度
- RecyclerView瀑布流加载图片实现
- Fresco和 RecyclerView 实现瀑布流 <图片是用本地图片来模拟网络图片的>
- Android使用OKHTTP网络框架请求数据,RecyclerView结合Glide展示图片,瀑布流布局样式
- Android使用RecyclerView实现瀑布流
- 使用RecyclerView实现瀑布流效果
- (4.1.11.1)Android中使用RecyclerView和CardView实现瀑布流效果(StaggeredGrid)
- Fresco,Retrofit 和 RecyclerView 实现瀑布流
- RecyclerView实现瀑布流
- recyclerView实现瀑布流
- 使用线程池和LruCache异步加载图片(防止错位)
- RecyclerView 瀑布流显示图片
- RecyclerView 瀑布流显示图片
- openstack 工作流workflows使用原理讲解
- Category 命名冲突检测
- 网络编程学习笔记一:Socket编程
- hdu 5791 two 多校联赛第五场
- JVM基础知识
- 使用RecyclerView和Glide实现图片瀑布流(防止错位)
- android studio启动时关闭上次打开的项目
- POST 提交XML 文件
- 堆和堆排序
- java消息队列ActiveMQ的简单使用
- lintcode graph-valid-tree 图是否是树
- 项目搭建输出 正式中要关闭
- iOS-使用Xcode自带单元测试UnitTest
- XML解析之DOM