RecyclerView实现瀑布流效果-阿里云开发者社区

开发者社区> 爆米花9958> 正文

RecyclerView实现瀑布流效果

简介: 在上一节,我们已经简单说过StaggeredGridLayoutManager的使用,这一节给出个具体的例子,我们利用他做一个照片墙的功能,先看下效果 首先是Item的布局item_recycler_layout.
+关注继续查看

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

    }
}
哈哈,其实和分割线差别不大,只是我们的分割线是透明的罢了,在这里我们要判断是否是最后一行,如果是,就不再绘制下面的分割线;判断是否是最后一列,如果是,就不再绘制右边的分割线,好了,效果实现!

参考:


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10055 0
Android自定义view水波纹效果案例
想必做安卓的小伙伴都知道,在一个项目中或多或少的会使用到自定义view,因为原生框架始终满足不了UI-UE的需求,入不了他们的法眼。下面简单写一个自定义view。
1375 0
手把手教你用RecyclerView实现猫眼电影选择效果
一、简介 在官方推出RecyclerView 控件之后,越来越多的人都使用它代替之前的ListView。除了最普通的列表显示,RecyclerView还可以其他的很多效果,例如Banner等。
1019 0
3.CCFadeOutTRTiles,部落格效果,跳动的方块特效,3D瓷砖晃动特效,破碎的3D瓷砖特效,瓷砖洗牌特效,分多行消失特效,分多列消失特效
 1 TiledGrid3D //TiledGrid3D //CCFadeOutTRTiles * action = CCFadeOutTRTiles::create(2, CCSize(20,20)); //CCFadeOutBLTiles * action = CCFadeOutBLTiles::create(2, CCSi
1651 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13869 0
141
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载