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

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

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

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

activity_waterfall
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recylerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="4dp" />
</LinearLayout>
item_waterfall 适配器中item布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/imgRV"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="center" />

    <TextView
        android:id="@+id/recycler_item_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:textColor="#F80F40"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin" />
</LinearLayout>

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

二、上java代码文件

  1. 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<WaterfullBean> 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<WaterfullBean> 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<RecyclerAdapter.LinearHolder> {
    private List<WaterfullBean> list;
    private Context context;

    public RecyclerAdapter(List<WaterfullBean> 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.

发布了14 篇原创文章 · 获赞 5 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/csdnwangyong/article/details/104971763
今日推荐