1.前言
利用RecyclerView配合StaggeredGridLayoutManager可以实现类似于淘宝和京东的商品瀑布流效果,下面是一个简单的使用例子。
2.例子
就不多讲了,直接上示例代码。
- 在页面的布局文件使用RecyclerView。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:orientation="vertical" >
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_staggered"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffaa"/>
</LinearLayout>
- 定义RecyclerView中每个item的布局文件。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhite"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv_pic"
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/colorBlack"
android:textSize="17sp" />
</LinearLayout>
- 编写item的bean(图片素材自找)。
package xyz.strasae.androidlearn.myapplication.bean;
import java.util.ArrayList;
import xyz.strasae.androidlearn.myapplication.R;
public class ItemInfo {
public int pic_id;
public String title;
public String desc;
public ItemInfo(int pic_id, String title, String desc) {
this.pic_id = pic_id;
this.title = title;
this.desc = desc;
}
public static int[] defaultItemImageArray = {R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4,
R.drawable.pic5, R.drawable.pic6, R.drawable.pic7, R.drawable.pic8, R.drawable.pic9,
R.drawable.pic10, R.drawable.pic11};
public static String[] defaultItemTitleArray = {"图片1", "图片2", "图片3", "图片4", "图片5", "图片6", "图片7", "图片8"
, "图片9", "图片10", "图片11"};
public static ArrayList<ItemInfo> getDefaultStag() {
ArrayList<ItemInfo> itemInfos = new ArrayList<ItemInfo>();
for(int i = 0; i < defaultItemImageArray.length; i++) {
itemInfos.add(new ItemInfo(defaultItemImageArray[i], defaultItemTitleArray[i], null));
}
return itemInfos;
}
}
- 编写适配器。根据item的布局文件编写ItemHolder;继承自RecyclerView.Adapter<RecyclerView.ViewHolder>,重写onCreateViewHolder方法和绑定持有者方法。
- 回调接口
package xyz.strasae.androidlearn.myapplication.widget;
import android.view.View;
public class RecyclerExtras {
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public interface OnItemLongClickListener {
void onItemLongClick(View view, int position);
}
public interface OnItemDeleteClickListener {
void onItemDeleteClick(View view, int position);
}
}
- 适配器
package xyz.strasae.androidlearn.myapplication.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import xyz.strasae.androidlearn.myapplication.R;
import xyz.strasae.androidlearn.myapplication.bean.ItemInfo;
import xyz.strasae.androidlearn.myapplication.widget.RecyclerExtras;
public class StaggeredAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements RecyclerExtras.OnItemClickListener, RecyclerExtras.OnItemLongClickListener {
private Context context;//设备上下文
private LayoutInflater inflater;//代码中获取控件
private ArrayList<ItemInfo> itemInfos;//item容器
public StaggeredAdapter(Context context, ArrayList<ItemInfo> itemInfos) {
this.context = context;
this.itemInfos = itemInfos;
inflater = LayoutInflater.from(context);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
RecyclerView.ViewHolder holder;
//获取布局文件
view = inflater.inflate(R.layout.item_staggered, parent, false);
holder = new ItemHolder(view);
return holder;
}
@Override
/**
* 绑定持有者
*/
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
ItemHolder itemHolder = (ItemHolder)holder;
itemHolder.iv_pic.setImageResource(itemInfos.get(position).pic_id);
itemHolder.tv_title.setText(itemInfos.get(position).title);
itemHolder.ll_item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(v, position);
}
}
});
itemHolder.ll_item.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
onItemLongClickListener.onItemLongClick(v, position);
return true;
}
});
}
private RecyclerExtras.OnItemLongClickListener onItemLongClickListener;
private RecyclerExtras.OnItemClickListener onItemClickListener;
public void setOnItemLongClickListener(RecyclerExtras.OnItemLongClickListener onItemLongClickListener) {
this.onItemLongClickListener = onItemLongClickListener;
}
public void setOnItemClickListener(RecyclerExtras.OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
//获取列表项类型
public int getItemViewType(int position) {
return 0;
}
@Override
//获取列表项编号
public long getItemId(int position) {
return position;
}
@Override
//获取列表项个数
public int getItemCount() {
return itemInfos.size();
}
@Override
public void onItemClick(View view, int position) {
Toast.makeText(context, "你点击了" + (position + 1) + " " + itemInfos.get(position).title, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(context, "你长按了" + (position + 1) + " " + itemInfos.get(position).title, Toast.LENGTH_SHORT).show();
}
/**
* 持有者 按照item的布局文件写
*/
private class ItemHolder extends RecyclerView.ViewHolder {
public LinearLayout ll_item;
public ImageView iv_pic;
public TextView tv_title;
public ItemHolder(View v) {
super(v);
ll_item = v.findViewById(R.id.ll_item);
iv_pic = v.findViewById(R.id.iv_pic);
tv_title = v.findViewById(R.id.tv_title);
}
}
}
- 页面中RecyclerView配合StaggeredGridLayoutManager使用。
- 装饰RecyclerView(item的空白间隔)。
package com.example.group.widget;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space; // 空白间隔
public SpacesItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.left = space; // 左边空白间隔
outRect.right = space; // 右边空白间隔
outRect.bottom = space; // 上方空白间隔
outRect.top = space; // 下方空白间隔
}
}
- 代码中RecyclerView配合StaggeredGridLayoutManager。
package xyz.strasae.androidlearn.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.os.Bundle;
import android.widget.LinearLayout;
import xyz.strasae.androidlearn.myapplication.adapter.StaggeredAdapter;
import xyz.strasae.androidlearn.myapplication.bean.ItemInfo;
import xyz.strasae.androidlearn.myapplication.widget.SpacesItemDecoration;
public class MainActivity extends AppCompatActivity {
private RecyclerView rv_staggered;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rv_staggered = findViewById(R.id.rv_staggered);
//第一个参数是每行(列)item的个数 第二个参数是横向排列还是纵向排列
StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3, LinearLayout.VERTICAL);
rv_staggered.setLayoutManager(manager);
StaggeredAdapter adapter = new StaggeredAdapter(this, ItemInfo.getDefaultStag());
adapter.setOnItemClickListener(adapter);//adapter本身就实现了这两个接口
adapter.setOnItemLongClickListener(adapter);
rv_staggered.setAdapter(adapter);
//设置动画
rv_staggered.setItemAnimator(new DefaultItemAnimator());
//设置装饰(这里这设置了间隔)
rv_staggered.addItemDecoration(new SpacesItemDecoration(3));
}
}