Android基础RecyclerView实现瀑布流(1)

关于瀑布流:

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格
前面已经讲了基础知识,现在来实现一个瀑布流的显示。

基础文章:android—UI—RecyclerViewd的基本使用(1)


参考文章:这里写链接内容


一.包引入

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.0'
    //包引入
    compile 'com.android.support:recyclerview-v7:+'
}

二.布局文件

主界面引入RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.newtestpubu.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</RelativeLayout>

RecyclerView的item布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/white">

    <ImageView
        android:id="@+id/masonry_item_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"/>
    <TextView
        android:id="@+id/masonry_item_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"/>
</LinearLayout>

这里添加一个ImageView和TextView

适配器类MasonryAdapter:

继承RecyclerView.Adapter<MasonryAdapter.MasonryView>,并重写里面的方法:

private List<Product> products;


    public MasonryAdapter(List<Product> list) {
        products = list;
    }

    @Override
    public MasonryView onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.masonry_item, viewGroup, false);
        return new MasonryView(view);
    }

    @Override
    public void onBindViewHolder(MasonryView masonryView, int position) {
        masonryView.imageView.setImageResource(products.get(position).getImg());
        masonryView.textView.setText(products.get(position).getTitle());

    }

    @Override
    public int getItemCount() {
        return products.size();
    }

    public static class MasonryView extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView textView;

        public MasonryView(View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.masonry_item_img);
            textView = (TextView) itemView.findViewById(R.id.masonry_item_title);
        }

    }

三个方法:
1. onCreateViewHolder()` 方法用于找到子item的布局文件,并返回视图。

2. onBindViewHolder()用于数据绑定,从列表里面获取数据,注意其中一个参数MasonryView masonryView是需要自定义的。 继承RecyclerView.ViewHolder` 用于找到item里面的布局控件。

public static class MasonryView extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView textView;

        public MasonryView(View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.masonry_item_img);
            textView = (TextView) itemView.findViewById(R.id.masonry_item_title);
        }

    }

3.getItemCount返回条目总数。

自定义类Product:

这个不解释,就是一个类,包括了所需的变量。

public class Product {
    private int img;
    private String title;

    public Product(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;
    }
}

使用RecyclerView:

在主Activity里面使用RecyclerView:
1.定义Product List 并做数据初始化,添加数据。
2.找到RecyclerView控件
3.设置LayoutManager,设置布局为 流式布局StaggeredGridLayoutManager,宽度为2.
4.绑定数据Adaper。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.recycler);
        //设置layoutManager
        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        //设置adapter
        initData();
        Log.d("xxxx", productList.toString());
        MasonryAdapter adapter = new MasonryAdapter(productList);
        recyclerView.setAdapter(adapter);
        }
        public void initData() {
        productList = new ArrayList<Product>();
        productList.add(new Product(R.drawable.ic_1, "美女1"));
        productList.add(new Product(R.drawable.ic_2, "美女1"));
        productList.add(new Product(R.drawable.ic_3, "美女1"));
        productList.add(new Product(R.drawable.ic_1, "美女1"));
        productList.add(new Product(R.drawable.ic_2, "美女1"));
        productList.add(new Product(R.drawable.ic_3, "美女1"));
        }

效果:

这里写图片描述

效果还不错:

添加分割栏:

大家都知道ItemDecoration 用于给每个item添加间隔的。
写一个SpacesItemDecoration 类继承 RecyclerView.ItemDecoration

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {

    private int space;

    public SpacesItemDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.left = space;
        outRect.right = space;
        outRect.bottom = space;
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.top = space;
        }
    }
}

间隔默认是透明的
这是原作者写的,继承后只重写了getItemOffsets一个方法,通过导入space的数值设置边框的大小,并判断是否是顶部的。

Activity引用:
添加在onCreate()里面:

//设置item之间的间隔
        SpacesItemDecoration decoration = new SpacesItemDecoration(100);
        recyclerView.addItemDecoration(decoration);

为了查看明显,设置的间隔比较大。
这里写图片描述

是不是图片变小了,是因为间隔的原因。
添加特效边框:
来自鸿洋的博客。

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    private Drawable mDivider;

    public DividerGridItemDecoration(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        //横线有效
        drawHorizontal(c, parent);
        //竖线无效
        drawVertical(c, parent);

    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();

        // 在每一个子控件的右侧画线
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            int right = child.getRight() - child.getPaddingRight();
            int left = right - mDivider.getIntrinsicWidth();
            final int top = child.getTop() + child.getPaddingTop();
            final int bottom = child.getTop() + child.getHeight() - child.getPaddingBottom();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }


    //    @Override
//    public void getItemOffsets(Rect outRect, int itemPosition,
//                               RecyclerView parent) {
//        int spanCount = getSpanCount(parent);
//        int childCount = parent.getAdapter().getItemCount();
//        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
//        {
//            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
//        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
//        {
//            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
//        } else {
//            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
//                    mDivider.getIntrinsicHeight());
//        }
//    }
// Item之间的留白
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
    }
}

这里使用了系统的styles 所以可以在文件里修改样式。详见基础文章。

这里写图片描述

这里只显示了底下的边框。左右边框没有画出来。没有解决。

PS 问题解决---->shape布局文件 添加宽度即可

<size android:height="4dp" android:width="3dp"/> 

添加删除动画

见基础文章

点击事件和长按事件

见基础文章

发布了85 篇原创文章 · 获赞 40 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/lw_zhaoritian/article/details/52538294
今日推荐