在上一节,我们已经简单说过StaggeredGridLayoutManager的使用,这一节给出个具体的例子,我们利用他做一个照片墙的功能,先看下效果
首先是Item的布局item_recycler_layout.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/iv_item_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
<TextView
android:id="@+id/tv_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:text="Text数据显示..."
android:textSize="16sp" />
</LinearLayout>
给每张照片写一个实体类
public class Photo {
private int img;
private String title;
public Photo() {
super();
}
public Photo(int img, String title) {
this.img = img;
this.title = title;
}
public int getImg() {
return img;
}
public void setImg(int img) {
this.img = img;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
自定义一个MyRecyclerAdapter
public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder> {
private List<Photo> photoList;
public MyRecyclerAdapter(List<Photo> list) {
super();
this.photoList = list;
}
@Override
public int getItemCount() {
return photoList.size();
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.item_tv.setText(photoList.get(position).getTitle());
holder.item_iv.setBackgroundResource(photoList.get(position).getImg());
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.item_recycler_layout, parent, false);
//view.setBackgroundColor(Color.RED);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView item_tv;
public ImageView item_iv;
public ViewHolder(View view) {
super(view);
item_tv = (TextView) view.findViewById(R.id.tv_item_text);
item_iv = (ImageView) view.findViewById(R.id.iv_item_img);
}
}
}
可以看出,MyRecyclerAdapter功能很简单,只实现了组件的加载和数据绑定
看下MainActivity
public class MainActivity extends Activity {
private RecyclerView mRecyclerView;
private LinearLayoutManager mLayoutManager;
private MyRecyclerAdapter mAdapter;
private List<Photo> mPhotoList;
private int[] indexs = new int[]{R.mipmap.a, R.mipmap.b,
R.mipmap.c, R.mipmap.e, R.mipmap.f, R.mipmap.g};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
//瀑布流式布局
StaggeredGridLayoutManager staggeredGridLayoutManager =
new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(staggeredGridLayoutManager);
initData();
// 创建适配器,并且设置
mAdapter = new MyRecyclerAdapter(mPhotoList);
// 设置adapter
mRecyclerView.setAdapter(mAdapter);
// 设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
// 设置间距
mRecyclerView.addItemDecoration(new SpaceItemDecoration(5));
}
private void initData() {
mPhotoList = new ArrayList<>();
for (int i = 0; i < indexs.length; i++) {
Photo photo = new Photo();
photo.setImg(indexs[i]);
photo.setTitle("图片" + i);
mPhotoList.add(photo);
}
}
}
在MainActivity中进行了数据的初始化,实际应用中,我们应该是从网络获取数据了,这也只是个model而已,前面我们说过给瀑布流加分割线的方法,但是分割线可能并不是我们想要的,例如我们只想有点间距就行了,无奈,RecyclerView并没有相关方法,我们通过改造分割线来实现下
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpaceItemDecoration(int space) {
this.space = space;
}
private int getSpanCount(RecyclerView parent) {
// 列数
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
return true;
}
}
return false;
}
private boolean isLastRow(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0) {
return true;
}
}
}
return false;
}
@Deprecated
public void getItemOffsets(Rect outRect, int itemPosition,View view,
RecyclerView parent, RecyclerView.State state) {
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
if (isLastRow(parent, itemPosition, spanCount, childCount)) {// 如果是最后一行,则不需要绘制底部
outRect.set(0, 0, space, 0);
} else if (isLastColum(parent, itemPosition, spanCount, childCount)) {// 如果是最后一列,则不需要绘制右边
outRect.set(0, 0, 0, space);
} else {
outRect.set(0, 0, space, space);
}
}
}
哈哈,其实和分割线差别不大,只是我们的分割线是透明的罢了,在这里我们要判断是否是最后一行,如果是,就不再绘制下面的分割线;判断是否是最后一列,如果是,就不再绘制右边的分割线
,好了,效果实现!
参考: