RecyclerView 已经出现有一年多了,看过的和没看过的都需要了解一下。


据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。


使用RecyclerView取代以往使用的ListView、GridView,使用SwipeRefreshLayout取代pull-to-refresh第三方库,打造更符合Material Design风格的APP。


开始之前,我们需要先导入这个。


Android Studio 在build 中加入


compile 'com.android.support:recyclerview-v7:+'


Eclipse 直接导入support-v7就可以了。



为了简单直接上Demo 代码:

首先上layout 布局文件:


由于需要用到下拉刷新,为了简单还是使用官方的组件:

android.support.v4.widget.SwipeRefreshLayout
<?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.recyclerview.demo.MainActivity">

    <android.support.v4.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/swiperefresh_layout"
        >
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recycler_view"
            ></android.support.v7.widget.RecyclerView>
    </android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>



那么接下来就需要编写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">

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






OK,既然做瀑布流,最流行的的那就是图片瀑布了。 我们先从Windows 中拷贝几张图片到项目中去。


完成这步,那就可以着手编写代码了。

和ListView 一样,既然使用相对复杂的东西,那么就需要重写适配器。 这里先不考虑他的点击事件。后面教程将会说到点击事件

public class MyAdapter extends RecyclerView.Adapter<PhotoView> {
    //定义数据模型
    private List<Photo> products;

    private MyItemClickListener mItemClickListener;

    //构造方法
    public MyAdapter(List<Photo> list) {
        products=list;
    }
    /**
     * 设置Item点击监听
     * @param listener
     */
    public void setOnItemClickListener(MyItemClickListener listener){
        this.mItemClickListener = listener;
    }
    //创建每一条小牧
    @Override
    public PhotoView onCreateViewHolder(ViewGroup viewGroup, int i) {
        //加载布局
        View view= LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.photo_item, viewGroup, false);

        return new PhotoView(view,mItemClickListener);
    }
    //banding数据的数据模型
    @Override
    public void onBindViewHolder(final PhotoView photoView, int position) {

        photoView.imageView.setImageResource(products.get(position).getImage());

        photoView.titleView.setText(products.get(position).getTitle());
    }
    //获取数据的大小
    @Override
    public int getItemCount() {
        return products.size();
    }
    //增加一项
    public void addData(int position,Photo photo) {
        products.add(position,photo);
        notifyItemInserted(position);
    }


    //删除一项
    public void removeData(int position) {
        products.remove(position);
        notifyItemRemoved(position);
    }
}




哔哔

再继续将实体类型添加进去,让适配器与实体进行判定。由于是模拟数据,那么我们就用本地的图片代替。所以实体为int 的图片ID


public class Photo {
    private int image;

    private String title;

    public int getImage() {
        return image;
    }

    public void setImage(int image) {
        this.image = image;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Photo(int image, String title) {
        this.image = image;
        this.title = title;
    }
}

OK,编写到这里,那么我们需要思考的是如何去实现这个瀑布的效果。


Recyclerview  提供了三个布局管理器。

LinearLayoutManager 水平或者垂直的Item视图。

GridLayoutManager 网格Item视图。

StaggeredGridLayoutManager 交错的网格Item视图。


这三个布局管理可以根据业务需求的不同设置不同的管理器,这里我们将使用


StaggeredGridLayoutManager 来实现 瀑布流的效果

 。



public class MainActivity extends AppCompatActivity {

    private final int[] imageRes = new int []{
        R.drawable.p1,R.drawable.p2,R.drawable.p3,R.drawable.p4,R.drawable.p5,R.drawable.p6,R.drawable.p7,R.drawable.p8
    };

    private MyAdapter myAdapter;

    private SwipeRefreshLayout mSwipeRefreshLayout;

    private RecyclerView recyclerView;

    private StaggeredGridLayoutManager mStaggerdGridLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView= (RecyclerView) findViewById(R.id.recycler_view);

        mStaggerdGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        //设置layoutManager
        recyclerView.setLayoutManager(mStaggerdGridLayoutManager);

        myAdapter = new MyAdapter(new ArrayList<Photo>());

        recyclerView.setAdapter(myAdapter);
        //设置item之间的间隔
        SpacesItemDecoration decoration=new SpacesItemDecoration(2);

        recyclerView.addItemDecoration(decoration);

        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swiperefresh_layout);

        mSwipeRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE);

        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                //  new MoreArticleTask().execute(mAdapter.getTopArticleId());
                Toast.makeText(getApplicationContext(),"刷新",Toast.LENGTH_SHORT).show();
                for(int i = 0 ; i < myAdapter.getItemCount() ;i ++) {
                    myAdapter.removeData(i);
                }
                refreshing();
                mSwipeRefreshLayout.setRefreshing(false);
            }
        });
        mSwipeRefreshLayout.post(new Runnable() {
            @Override
            public void run() {
                mSwipeRefreshLayout.setRefreshing(true);
                refreshing();
                mSwipeRefreshLayout.setRefreshing(false);
            }
        });
    }

    //用于刷新的方法  主要使用适配器中addData 方法
    private void refreshing(){
        for(int i = 0 ; i < imageRes.length; i++){
            Photo photo = new Photo(imageRes[(int)(Math.random()*imageRes.length)],"这是第"+(int)(Math.random()*imageRes.length)+":"+i+"张图片");
            myAdapter.addData(i,photo);
        }
    }

    private void loadMore(){

    }
}



其中我们为了实现 瀑布流的需要设置下划线 也就是空隙:


//设置item之间的间隔
        SpacesItemDecoration decoration=new SpacesItemDecoration(2);

        recyclerView.addItemDecoration(decoration);
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;
        }
    }
}

OK ,那么实现线性布局 可以直接这样写

//设置layoutManager

recyclerView.setLayoutManager(<span class="crayon-r">new</span><span class="crayon-h"> </span><span class="crayon-e">LinearLayoutManager</span><span class="crayon-sy">(</span><span class="crayon-r">this</span><span class="crayon-sy">)</span><span class="crayon-sy"></span>);

Demo :下载地址

点击打开链接

最后效果图

ios uicollectview 图片瀑布流_xml