天天看點

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

繼續閱讀