在上一節,我們已經簡單說過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: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) {
public String getTitle() {
return title;
public void setTitle(String title) {
}
自定義一個MyRecyclerAdapter
public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder> {
private List<Photo> photoList;
public MyRecyclerAdapter(List<Photo> list) {
this.photoList = list;
@Override
public int getItemCount() {
return photoList.size();
public void onBindViewHolder(ViewHolder holder, int position) {
holder.item_tv.setText(photoList.get(position).getTitle());
holder.item_iv.setBackgroundResource(photoList.get(position).getImg());
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};
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) {
if ((pos + 1) % spanCount == 0)// 如果是最後一列,則不需要繪制右邊
{
return true;
}
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 false;
private boolean isLastRow(RecyclerView parent, int pos, int spanCount,
int childCount) {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最後一行,則不需要繪制底部
// StaggeredGridLayoutManager 且縱向滾動
// 如果是最後一行,則不需要繪制底部
if (pos >= childCount)
} else
// StaggeredGridLayoutManager 且橫向滾動
if ((pos + 1) % spanCount == 0) {
@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);
哈哈,其實和分割線差别不大,隻是我們的分割線是透明的罷了,在這裡我們要判斷是否是最後一行,如果是,就不再繪制下面的分割線;判斷是否是最後一列,如果是,就不再繪制右邊的分割線,好了,效果實作!
參考:
http://my.oschina.net/yaly/blog/515412 http://www.bubuko.com/infodetail-999014.html http://blog.csdn.net/lmj623565791/article/details/45059587 http://www.2cto.com/kf/201511/450814.html