介绍
在许多电商的 App 当中都需要网格交错的布局进行商品的展示,因为不同商品的外观与尺寸都是不一样的,例如,一台电视可能需要横向的尺寸比较长一些,而冰箱就需要纵向的尺寸长一些,所以要是通过尺寸相同的网格布局来实现必然会有部分商品的图片被压缩变形。在这种情况下根据商品尺寸的不同来展示各种商品就可以使用瀑布流网格布局。通过 RecyclerView 实现瀑布流网格布局时需要使用 StaggeredGridLayoutManager 类,然后在适配器中动态设置每个网格的尺寸,最后 RecyclerView将适配器中的数据以瀑布流网格布局的形式显示在界面当中。
相关方法
- setOrientation:设置布局排列的方向。
- setReverseLayout:设置相反方向的布局排列。
- setSpanCount:设置网格的列数。
- StaggeredGridLayoutManager:构造方法设置网格的列数和方向。
例子
RecyclerView的瀑布流网格布局
编写布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--列表控件-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:background="#EEEEEE"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</RelativeLayout>
创建layout_item03.xml
<?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:orientation="vertical">
<!--显示图片-->
<ImageView
android:id="@+id/icon"
android:layout_width="200dp"
android:layout_height="0dp"
android:layout_weight="5"
android:layout_gravity="center_horizontal" />
<!--显示图片的标题-->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:textSize="17sp" />
</LinearLayout>
编写StaggeredAdapter
public class StaggeredAdapter extends RecyclerView.Adapter<StaggeredAdapter.MyViewHolder> {
private List<Integer> heights;
OnItemClickListener mListener;
//图标数组
private int[] icons = {
R.drawable.img01, R.drawable.img02, R.drawable.img03,
R.drawable.img04, R.drawable.img05, R.drawable.img06,
R.drawable.img07, R.drawable.img08, R.drawable.img09,
R.drawable.img10, R.drawable.img11, R.drawable.img12
};
//名字数组,引用资源文件中的文字
private int[] names = {
R.string.name1, R.string.name2, R.string.name3,
R.string.name4, R.string.name5, R.string.name6,
R.string.name7, R.string.name8, R.string.name9,
R.string.name10, R.string.name11, R.string.name12
};
private Context lContext; //上下文
public List<Integer> listIcon = new ArrayList<Integer>(); //图标集合
public List<Integer> listName = new ArrayList<Integer>(); //名称集合
public StaggeredAdapter(Context context) {
lContext = context;
getRandomHeight();
//设置菜单行数与行内图标、名称、信息
for (int i = 0; i < 12; i++) {
listIcon.add(icons[i]);
listName.add(names[i]);
}
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//获取列表中每行的布局文件
View view = LayoutInflater.from(lContext).inflate(R.layout.layout_item03, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//设置图标
holder.img.setBackgroundResource(listIcon.get(position));
//设置名称
holder.name.setText(listName.get(position));
//得到item的LayoutParams布局参数
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = heights.get(position); //把随机的高度赋予item布局
holder.itemView.setLayoutParams(params);//把params设置给item布局
holder.img.setBackgroundResource(listIcon.get(position));//设置图片
holder.name.setText(listName.get(position)); //为控件绑定数据
if (mListener != null) { //如果设置了监听那么它就不为空,然后回调相应的方法
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getLayoutPosition();//获取当前点击item的位置pos
//把事件交给我们实现的接口那里处理
mListener.ItemClickListener(holder.itemView, pos);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = holder.getLayoutPosition();//获取当前点击item的位置pos
//把事件交给我们实现的接口那里处理
mListener.ItemLongClickListener(holder.itemView, pos);
return true;
}
});
}
}
@Override
public int getItemCount() {
return listIcon.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name; //名字
public ImageView img; //图标
//获取相关控件
public MyViewHolder(View itemView) {
super(itemView); //这里包含了this.itemView=itemView;
name = (TextView) itemView.findViewById(R.id.title);
img = (ImageView) itemView.findViewById(R.id.icon);
}
}
//得到随机item的高度
private void getRandomHeight() {
heights = new ArrayList<>(); //网格高度的集合
for (int i = 0; i < 12; i++) {
//随机产生网格高度并添加到集合中,random()得到的是double类型
heights.add((int) (400 + Math.random() * 100));
}
}
//单击事件与长按事件的接口
public interface OnItemClickListener {
void ItemClickListener(View view, int position);
void ItemLongClickListener(View view, int position);
}
//设置单击事件的方法
public void setOnClickListener(OnItemClickListener listener) {
this.mListener = listener;
}
}
编写StaggeredGridRecyclerActivity
该Activity实现了StaggeredAdapter中的OnItemClickListener
public class StaggeredGridRecyclerActivity extends AppCompatActivity {
private RecyclerView mRecyclerView; //列表控件
private StaggeredAdapter adapter; //适配器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staggered_grid_recycler);
//列表控件
mRecyclerView = (RecyclerView) this.findViewById(R.id.recyclerview);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//设置RecyclerView布局管理器为2列垂直排布
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager
(2, StaggeredGridLayoutManager.VERTICAL));
//创建适配器对象
adapter = new StaggeredAdapter(this);
mRecyclerView.setAdapter(adapter); //设置适配器
adapter.setOnClickListener(new StaggeredAdapter.OnItemClickListener() {
//单击事件
@Override
public void ItemClickListener(View view, int position) {
Toast.makeText(StaggeredGridRecyclerActivity.this,"单击了干员:"
+adapter.listName.get(position),Toast.LENGTH_SHORT).show();
}
//长按事件
@Override
public void ItemLongClickListener(View view, int position) {
//adapter.listName.remove(position);
//adapter.listIcon.remove(position);
//长按删除,在适配器中移除
adapter.notifyItemRemoved(position);
}
});
}
}
效果
|