1. 程式人生 > >RecyclerView的簡單使用以及實現瀑布流效果

RecyclerView的簡單使用以及實現瀑布流效果

RecyclerView

簡介

RecyclerView是support.v7包中的控制元件,可以認為是ListView和GridView的增強版,RecyclerView提供了一個耦合度更低的方式來複用ViewHolder,可以更輕鬆的實現瀑布流的效果,為增加和刪除條目提供了預設的動畫效果.

目前SDK中提供了三種自帶的LayoutManager:(LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager)

簡單使用


1:新增依賴

在AS的build.gradle中新增依賴,然後同步一下就可以引入依賴包:

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

2:編寫程式碼

先寫好佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_recycle_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycleView" 
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
</RelativeLayout>
在其對應Activity中獲取RecycleView,宣告好佈局管理器,Adapter,初始化資料,以及設定分割線等...
package com.goblin.esx.gridlist.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;

import com.goblin.esx.gridlist.MyItemDecoration;
import com.goblin.esx.gridlist.R;
import com.goblin.esx.gridlist.adapter.MyRecyclerViewAdapter;

import java.util.ArrayList;
import java.util.List;

public class RecyclerViewActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    //標題的集合
    private List<String> title   = new ArrayList<>();
    //內容的集合
    private List<String> content = new ArrayList<>();
    private int          NUMBER  = 40;
    private MyRecyclerViewAdapter myRecyclerViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycle_view);
        recyclerView = (RecyclerView) findViewById(R.id.recycleView);
        //初始化資料
        initData();
//        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //實現網格效果的佈局管理器
        GridLayoutManager layoutManager=new GridLayoutManager(this,3);
        //設定佈局管理器
        recyclerView.setLayoutManager(layoutManager);
        //設定為垂直佈局,這是預設的
        layoutManager.setOrientation(OrientationHelper.VERTICAL);
//        layoutManager.setOrientation(OrientationHelper.HORIZONTAL);
        myRecyclerViewAdapter = new MyRecyclerViewAdapter(RecyclerViewActivity.this, title, content);
        //設定點選事件
        myRecyclerViewAdapter.setOnMyItemClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Toast.makeText(RecyclerViewActivity.this, "您點選咯---->"+v.getTag(), Toast.LENGTH_SHORT).show();
            }
        });
        recyclerView.setAdapter(myRecyclerViewAdapter);
        //設定分隔線
        recyclerView.addItemDecoration(new MyItemDecoration(this));
    }

    private void initData() {
        for (int i = 0; i < NUMBER; i++) {
            title.add("標題" + i);
            content.add("內容" + i);
        }
    }

}
接下來設定Adapter
package com.goblin.esx.gridlist.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.goblin.esx.gridlist.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017-3-20.
 */

public class MyRecyclerViewAdapter extends RecyclerView.Adapter {
    //標題的集合
    private List<String> title   = new ArrayList<>();
    //內容的集合
    private List<String> content = new ArrayList<>();
    private Context context;

    public MyRecyclerViewAdapter(Context context, List<String> title, List<String> content) {
        this.title = title;
        this.content = content;
        this.context = context;
    }

    //建立ChildView
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(context, R.layout.item_list_adapter, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    //將資料繫結到每一個childView中
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ViewHolder myHolder = (ViewHolder) holder;
        myHolder.ivLeft.setImageResource(R.drawable.goblin);
        myHolder.tvTitle.setText(title.get(position));
        myHolder.tvContent.setText(content.get(position));
        //設定標記
        myHolder.itemView.setTag(title.get(position));
        myHolder.itemView.setOnClickListener(listener);
    }

    private View.OnClickListener listener;

    public void setOnMyItemClickListener(View.OnClickListener listener) {
        this.listener = listener;
    }

    //得到child的數量
    @Override
    public int getItemCount() {
        return title.size();
    }

    // 通過holder的方式來初始化每一個ChildView的內容
    static class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView ivLeft;
        private TextView  tvTitle;
        private TextView  tvContent;

        public ViewHolder(View itemView) {
            super(itemView);
            ivLeft = (ImageView) itemView.findViewById(R.id.iv_left);
            tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
            tvContent = (TextView) itemView.findViewById(R.id.tv_content);

        }
    }
}
最後設定分割線,這樣簡單的RecyclerView就實現咯
package com.goblin.esx.gridlist;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Administrator on 2017-3-20.
 */

public class MyItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDividerDarwable;
    private int mDividerHight = 1;
    private Paint mColorPaint;


    public final int[] ATRRS = new int[]{android.R.attr.listDivider};

    public MyItemDecoration(Context context) {
        final TypedArray ta = context.obtainStyledAttributes(ATRRS);
        this.mDividerDarwable = ta.getDrawable(0);
        ta.recycle();
    }

    /*
     int dividerHight  分割線的線寬
     int dividerColor  分割線的顏色
     */
    public MyItemDecoration(Context context, int dividerHight, int dividerColor) {
        this(context);
        mDividerHight = dividerHight;
        mColorPaint = new Paint();
        mColorPaint.setColor(dividerColor);
    }

    /*
     int dividerHight  分割線的線寬
     Drawable dividerDrawable  圖片分割線
     */
    public MyItemDecoration(Context context, int dividerHight, Drawable dividerDrawable) {
        this(context);
        mDividerHight = dividerHight;
        mDividerDarwable = dividerDrawable;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        //畫水平和垂直分割線
        drawHorizontalDivider(c, parent);
        drawVerticalDivider(c, parent);
    }

    public void drawVerticalDivider(Canvas c, RecyclerView parent) {
        final 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 top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;

            int left = 0;
            int right = 0;

            //左邊第一列
            if ((i % 3) == 0) {
                //item左邊分割線
                left = child.getLeft();
                right = left + mDividerHight;
                mDividerDarwable.setBounds(left, top, right, bottom);
                mDividerDarwable.draw(c);
                if (mColorPaint != null) {
                    c.drawRect(left, top, right, bottom, mColorPaint);
                }
                //item右邊分割線
                left = child.getRight() + params.rightMargin - mDividerHight;
                right = left + mDividerHight;
            } else {
                //非左邊第一列
                left = child.getRight() + params.rightMargin - mDividerHight;
                right = left + mDividerHight;
            }
            //畫分割線
            mDividerDarwable.setBounds(left, top, right, bottom);
            mDividerDarwable.draw(c);
            if (mColorPaint != null) {
                c.drawRect(left, top, right, bottom, mColorPaint);
            }

        }
    }

    public void drawHorizontalDivider(Canvas c, RecyclerView parent) {

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            final int left = child.getLeft() - params.leftMargin - mDividerHight;
            final int right = child.getRight() + params.rightMargin;
            int top = 0;
            int bottom = 0;

            // 最上面一行
            if ((i / 3) == 0) {
                //當前item最上面的分割線
                top = child.getTop();
                //當前item下面的分割線
                bottom = top + mDividerHight;
                mDividerDarwable.setBounds(left, top, right, bottom);
                mDividerDarwable.draw(c);
                if (mColorPaint != null) {
                    c.drawRect(left, top, right, bottom, mColorPaint);
                }
                top = child.getBottom() + params.bottomMargin;
                bottom = top + mDividerHight;
            } else {
                top = child.getBottom() + params.bottomMargin;
                bottom = top + mDividerHight;
            }
            //畫分割線
            mDividerDarwable.setBounds(left, top, right, bottom);
            mDividerDarwable.draw(c);
            if (mColorPaint != null) {
                c.drawRect(left, top, right, bottom, mColorPaint);
            }
        }
    }
}

高階使用


RecyclerView實現瀑布流,以及RecyclerView增加和刪除條目

設定佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_recycler"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycle_view" android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>
    <ImageView
        android:id="@+id/iv_add" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:layout_margin="10dp"
        android:background="@drawable/selector_iv_add"/>

</RelativeLayout>


設定Adapter

package com.goblin.esx.gridlist.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.goblin.esx.gridlist.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017-3-20.
 */

public class MyRecycleSaultAdapter extends RecyclerView.Adapter {
    private Context context;
    private List<Integer> list = new ArrayList<>();
    private List<Integer> mHeights;

    public MyRecycleSaultAdapter(Context context, List<Integer> list) {
        this.context = context;
        this.list = list;
        mHeights = new ArrayList<>();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(context, R.layout.item_recycle_adapter, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ViewHolder myHolder = (ViewHolder) holder;
        // 隨機高度, 模擬瀑布效果.
        if (mHeights.size() <= position) {
            mHeights.add((int) (300 + Math.random() * 100));
        }

        ViewGroup.LayoutParams lp = myHolder.ivImage.getLayoutParams();
        lp.height = mHeights.get(position);
        myHolder.ivImage.setLayoutParams(lp);

        Integer ivId = list.get(position);
        myHolder.ivImage.setImageResource(ivId);
        //設定標記
        myHolder.itemView.setTag(position);
        myHolder.itemView.setOnClickListener(listener);
        myHolder.itemView.setOnLongClickListener(longListener);
    }

    //點選事件
    private View.OnClickListener listener;

    public void setOnMyItemClickListener(View.OnClickListener listener) {
        this.listener = listener;
    }

    //長按事件
    private View.OnLongClickListener longListener;

    public void setOnMyItemLongClickListener(View.OnLongClickListener longListener) {
        this.longListener = longListener;
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView ivImage;

        public ViewHolder(View itemView) {
            super(itemView);
            ivImage = (ImageView) itemView.findViewById(R.id.iv_image);
        }
    }
    //向集合中新增資料
    public void addList(int position) {
        list.add(position, R.drawable.x);
        notifyItemInserted(position);
    }
    //移除集合中的資料
    public void removeList(int position) {
        list.remove(position);
        notifyItemRemoved(position);
    }
}

Activity裡面設定點選事件,長按刪除事件等......

package com.goblin.esx.gridlist.activity;

import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.goblin.esx.gridlist.MyItemDecoration;
import com.goblin.esx.gridlist.R;
import com.goblin.esx.gridlist.adapter.MyRecycleSaultAdapter;

import java.util.ArrayList;
import java.util.List;

public class RecyclerSaultActivity extends AppCompatActivity {

    private RecyclerView          recycleView;
    private MyRecycleSaultAdapter myRecycleAdapter;
    private List<Integer> list   = new ArrayList<>();
    private int           NUMBER = 20;
    private ImageView ivAdd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler);
        ivAdd = (ImageView) findViewById(R.id.iv_add);
        //初始化資料
        initData();
        recycleView = (RecyclerView) findViewById(R.id.recycle_view);
        myRecycleAdapter = new MyRecycleSaultAdapter(this, list);
        // 錯列網格佈局
        recycleView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager
                .VERTICAL));
        //設定間距
        recycleView.addItemDecoration(new SpacesItemDecoration(8));
        recycleView.setItemAnimator(new DefaultItemAnimator());
        recycleView.setAdapter(myRecycleAdapter);
        //設定分隔線
        recycleView.addItemDecoration(new MyItemDecoration(this));
        //新增的點選事件
        ivAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(RecyclerSaultActivity.this, "您新增咯一張圖片", Toast.LENGTH_SHORT).show();
                myRecycleAdapter.addList(1);
            }
        });
        //點選事件
        myRecycleAdapter.setOnMyItemClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(RecyclerSaultActivity.this, "您點選咯"+v.getTag(), Toast.LENGTH_SHORT).show();
            }
        });
        //長按事件(刪除)
        myRecycleAdapter.setOnMyItemLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                myRecycleAdapter.removeList(1);
                Toast.makeText(RecyclerSaultActivity.this, "您刪除咯一張圖片"+v.getTag(), Toast.LENGTH_SHORT).show();
                //不返回true,鬆手還會去執行單擊事件
                return true;
            }
        });
    }

    private void initData() {
        for (int i = 0; i < NUMBER; i++) {
            list.add(R.drawable.a);
            list.add(R.drawable.b);
            list.add(R.drawable.c);
            list.add(R.drawable.d);
            list.add(R.drawable.e);
            list.add(R.drawable.f);
            list.add(R.drawable.g);
        }
    }


    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;
            } else if (parent.getChildAdapterPosition(view) == 5) {
                outRect.top = space * 2;
            }

        }
    }
}

圖片的佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <ImageView
        android:id="@+id/iv_image"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:background="@drawable/a"
        android:gravity="center" />
</LinearLayout>

給新增的圖片按鈕設定狀態選擇器

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/add"/>
    <item android:drawable="@drawable/add_pressed"/>
</selector>