天天看点

RecyclerView实现瀑布流效果

在上一节,我们已经简单说过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

继续阅读