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

Lani ·
更新时间:2024-09-20
· 552 次阅读

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

以下会写从布局到java代码以及用到的工具类都写出来,供大家参考

一、首先上两个布局xml文件

activity_waterfall item_waterfall 适配器中item布局

其中最外层 LinearLayout 和imageview的高度必须设置为 wrap_content

二、上java代码文件

WaterfallActivity.java import android.os.Bundle; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import com.bumptech.glide.Glide; import com.example.mytest.R; import com.example.mytest.adapter.RecyclerAdapter; import com.example.mytest.bean.WaterfullBean; import com.example.mytest.util.AGlide; import com.example.mytest.view.StaggeredDividerItemDecoration; import java.util.ArrayList; import java.util.List; import java.util.Random; import butterknife.BindView; import butterknife.ButterKnife; /** * 描述 实现瀑布流效果 * by creat wyp 2020/3/13 */ public class WaterfallActivity extends BaseActivtiy { @BindView(R.id.recylerview) RecyclerView recyclerView; private RecyclerAdapter recyclerAdapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public int getLayoutId() { return R.layout.activity_waterfall; } @Override protected void initView() { } @Override protected void initData() { recyclerAdapter = new RecyclerAdapter(getData(),this); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//防止item交换位置 recyclerView.setLayoutManager(layoutManager); //以下三行去掉 RecyclerView 动画代码,防止闪烁 ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); ((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); recyclerView.getItemAnimator().setChangeDuration(0); recyclerView.setAdapter(recyclerAdapter); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); layoutManager.invalidateSpanAssignments();//防止第一行到顶部有空白 } }); } @Override public void initOther() { } private List getData() { String[] names = {"晓风残月","杨柳依依","二月春分","杏花诗雨随风至,","中华少年不屈不挠,少年强中国强,壮我中国魂","铁马冰河","庐山迷雾","竹林幽潭","大唐雄风","暖风袭的游人醉","一切疫情都是纸老虎", "我自横刀向天笑,去留肝胆两昆仑","春如一夜春风留春痕","人生若只是初见","风雨不曾动我心","皎皎明月","流觞","若水三千"}; String[] imgHeight={"260","300","100","220","180","260","200","320","200","300","250","280","150","240","200","280"}; String path1 = "http://img0.imgtn.bdimg.com/it/u=1595128334,82706458&fm=26&gp=0.jpg"; String path2 = "http://img2.imgtn.bdimg.com/it/u=3663359702,1992818410&fm=26&gp=0.jpg"; String path3 = "http://img1.imgtn.bdimg.com/it/u=1935467811,195414982&fm=26&gp=0.jpg"; String path4 = "http://img1.imgtn.bdimg.com/it/u=2939811527,4256764476&fm=26&gp=0.jpg"; String path5 = "http://img5.imgtn.bdimg.com/it/u=2433540234,3071973675&fm=11&gp=0.jpg"; String path6 = "http://img0.imgtn.bdimg.com/it/u=2252193884,3728807126&fm=11&gp=0.jpg"; String path7 = "http://img5.imgtn.bdimg.com/it/u=3404931913,2642312894&fm=26&gp=0.jpg"; String path8 = "http://img2.imgtn.bdimg.com/it/u=3656563200,458275370&fm=26&gp=0.jpg"; String path9 = "http://img3.imgtn.bdimg.com/it/u=272626499,1769311702&fm=11&gp=0.jpg"; String path10 = "http://img2.imgtn.bdimg.com/it/u=3656563200,458275370&fm=26&gp=0.jpg"; String path11 = "http://img0.imgtn.bdimg.com/it/u=1641821854,2305393622&fm=15&gp=0.jpg"; String path12 = "http://img0.imgtn.bdimg.com/it/u=1641821854,2305393622&fm=15&gp=0.jpg"; String path13 = "http://img.mp.itc.cn/upload/20161019/177f8df712764c3ea2355a5dfed785da_th.gif"; String path14 = "http://img3.imgtn.bdimg.com/it/u=547082689,2172122564&fm=11&gp=0.jpg"; String path15 = "http://img4.imgtn.bdimg.com/it/u=4213113895,2522756905&fm=11&gp=0.jpg"; String path16 = "http://img4.imgtn.bdimg.com/it/u=3043589085,1773439913&fm=26&gp=0.jpg"; String[] imgUrs={path1,path2,path3,path4,path5,path6,path7,path8,path9,path10,path11,path12,path13,path14,path15,path16}; List waterfullList = new ArrayList(); for (int i = 0; i <16 ; i++) { WaterfullBean bean=new WaterfullBean(); bean.img=imgUrs[i]; bean.tv=names[i]; bean.imgHeight = imgHeight[i]; waterfullList.add(bean); } return waterfullList; } //获取随机字符串的 测试textview数据值 可以测试用 不用就删除 private String getRandomLengthName(String name) { Random random = new Random(); int length = random.nextInt(10) + 1;//取0~20之间的一个随机数 StringBuilder builder = new StringBuilder(); for (int i = 0; i < length; i++) { builder.append(name);//字符串拼接 } return builder.toString(); } }

实际上项目中让后台服务给返回图片的地址和图片的宽高,我现在写测试就自己定义了 String[] imgHeight高,至于宽在适配器中固定写了350

androidxGoogle 2018 IO 大会推出了 ,用于替换原来的 Android扩展库,将原来的android.*替换成androidx.*

我自己用的是Android新的扩展库 AndroidX,如果用还是android.的可以自己导入对应的库,关于ButterKnife的注解获取id 就不说了,估计现在也很普及,网上很多资料不清楚可以自己看

RecyclerView.LayoutManager提供了三个实现类其中LinearLayoutManager 现行管理器,支持横向、纵向,GridLayoutManager 网格布局管理器,StaggeredGridLayoutManager 瀑布就式布局管理器,有兴趣的可以细细研究一下,关于瀑布流就是用StaggeredGridLayoutManager

代码中注意以下:

防止item交换位置

layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE); 以下三行去掉 RecyclerView 动画代码,防止闪烁 ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); ((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); recyclerView.getItemAnimator().setChangeDuration(0); 2、RecyclerAdapter import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.example.mytest.R; import com.example.mytest.bean.WaterfullBean; import com.example.mytest.util.ScreenUtils; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; /** * 描述 瀑布流适配器 * by creat wyp 2020/3/19 */ public class RecyclerAdapter extends RecyclerView.Adapter { private List list; private Context context; public RecyclerAdapter(List list,Context context){ this.context=context; this.list=list; } @NonNull @Override public LinearHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.item_waterfall, parent,false); //new一个我们的ViewHolder,findViewById操作都在LinearHolder的构造方法中进行了 LinearHolder simpleViewHolder = new LinearHolder(view); simpleViewHolder.setIsRecyclable(true); return simpleViewHolder; } @Override public void onBindViewHolder(@NonNull LinearHolder holder, int position) { holder.recycler_item.setText(list.get(position).tv); //动态设置控件宽高 //先算出item的宽度,给RecyclerView设置完间隔后,屏幕宽度-间隔*3 就是两个item的宽度和了, // 故 itemWidth=(ScreenWidth-间隔*3)/2 ,换算过程,记得只有最终结果转int,计算过程用float,防止莫名其妙的四舍五入导致height过多偏差。 ViewGroup.LayoutParams layoutParams=holder.imgRV.getLayoutParams(); float itemWidth=(ScreenUtils.getScreenWidth(holder.itemView.getContext())-5*3)/2; layoutParams.width= (int) itemWidth; float scale=(itemWidth+0f)/350;//这儿是图片的宽度 目前写死了 自己可以根据自己实际情况替换掉 layoutParams.height= (int) (Integer.parseInt(list.get(position).imgHeight)*scale); holder.imgRV.setLayoutParams(layoutParams); Glide.with(context).load(list.get(position).img).override(layoutParams.width,layoutParams.height).into(holder.imgRV); } @Override public int getItemCount() { return list.size(); } class LinearHolder extends RecyclerView.ViewHolder { @BindView(R.id.recycler_item_tv) TextView recycler_item; @BindView(R.id.imgRV) ImageView imgRV; public LinearHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } } 3、WaterfullBean /** * 描述 * by creat wyp 2020/3/19 */ public class WaterfullBean { public String tv; public String img; public String imgHeight; } 到此就测试的瀑布流就完成了,至于用到项目中自己实际调式即可

如果发现了问题欢迎大家留言,我及时修改。毕竟改了自己以后我自己也可以copy.


作者:csdnwangyong



图片 recyclerview 瀑布 瀑布流 自适应 Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号