「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
前言
昨天我们使用
RecyclerView
实现了网格布局,通过你的举一反三
天赋,你成功的被窝读书中的签到样式,今天我们就来学习如何利用RecyclerView
实现实际开发中经常遇到的瀑布流布局
老样子,先来看看现在app中的使用场景吧
看着很复杂对吧,有的高,有的矮,其实简单的实现并不是很难,我们现在就开始吧
还是老样子,xml声明recyclerview
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StaggerActivity">
<androidx.recyclerview.widget.RecyclerView
//控件id
android:id="@+id/rv_stagger"
//距离左侧距离,防止贴边
android:layout_marginLeft="15dp"
//充满父布局
android:layout_width="match_parent"
//高度自适应
android:layout_height="wrap_content"
//设置约束条件
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
Activity
private RecyclerView mRvStagger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stagger);
initView();
}
private void initView() {
//初始化布局
mRvStagger = findViewById(R.id.rv_stagger);
//设置瀑布流专属布局管理器;不会限制item的宽高
mRvStagger.setLayoutManager(new StaggeredGridLayoutManager(2,RecyclerView.VERTICAL));
//模拟真实数据环境
List<StaggerBean> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(new StaggerBean("测试"+i));
}
//实例化适配器
StaggerAdapter staggerAdapter = new StaggerAdapter(this, list);
//设置适配器
mRvStagger.setAdapter(staggerAdapter);
}
复制代码
StaggerBean
public class StaggerBean {
//需要显示的商品名称
public String content;
//每个item的高度
public int height;
//构造函数,必填商品名称
public StaggerBean(String content) {
this.content = content;
}
}
复制代码
适配器
public class StaggerAdapter extends RecyclerView.Adapter<StaggerAdapter.ViewHolder> {
private final Context context;
private final List<StaggerBean> list;
public StaggerAdapter(Context context, List<StaggerBean> list) {
this.context = context;
this.list = list;
}
@NonNull
@NotNull
@Override
public ViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
//加载布局
View root = LayoutInflater.from(context).inflate(R.layout.item_stagger, parent, false);
return new ViewHolder(root);
}
@Override
public void onBindViewHolder(@NonNull @NotNull StaggerAdapter.ViewHolder holder, int position) {
//获取当前下标应该渲染的数据
StaggerBean staggerBean = list.get(position);
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) holder.mItemIv.getLayoutParams();
//如果实体类中的高度是0就代表是第一次加载,我们要随机一个数值给他,模拟我们的高度不等效果
if (staggerBean.height == 0) {
//设置一个随机数,值为100-300随机
Random random = new Random();
int i = random.nextInt(ImageUtil.dp2px(context, 300) - ImageUtil.dp2px(context, 100)) + ImageUtil.dp2px(context, 100);
//存到当前实体类
staggerBean.height = i;
//先给图片设置上高度
layoutParams.height = i;
} else {
//如果已经有高度说明是第二个加载当前数据,直接使用实体类的数据即可
layoutParams.height = staggerBean.height;
}
//设置图片高度
holder.mItemIv.setLayoutParams(layoutParams);
//渲染商品名称
holder.mItemTv.setText(staggerBean.content);
}
@Override
public int getItemCount() {
//数量
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
//初始化控件
private final ImageView mItemIv;
private final TextView mItemTv;
public ViewHolder(@NonNull @NotNull View convertView) {
super(convertView);
mItemIv = convertView.findViewById(R.id.item_iv);
mItemTv = convertView.findViewById(R.id.item_tv);
}
}
}
复制代码
item
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/item_iv"
//宽度设定一个值,一般根据设计图来确定
android:layout_width="150dp"
//随便给个背景,好识别
android:background="@color/teal_200"
//高度随便,反正是动态设置,这里面-100都行
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
//距离上方距离
android:layout_marginTop="10dp"
//内部距离父布局距离
android:padding="10dp"
//约束条件
app:layout_constraintLeft_toLeftOf="@id/item_iv"
app:layout_constraintRight_toRightOf="@id/item_iv"
app:layout_constraintTop_toBottomOf="@id/item_iv" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
效果
很完美,如果你要做刷新,你可能会碰到许许多多的bug,嘎嘎嘎嘎嘎