RecycleView简单介绍

RecycleView相对于原来的ListView和GridView要灵活很多,可以很快的在listView和gridView以及瀑布流之间进行切换,它主要提供了3中布局方式,LinearLayoutManager(ListView)、GridLayoutManager(GridView)、StaggeredGridLayoutManager(瀑布流)

1、主界面,已经写了3个布局类型 只需要简单的切换,就可以看到不同的效果
public class MainActivity extends AppCompatActivity {

    private RecyclerView rv;
    private ArrayList<String> mDatas;
    private MyAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);
        initDatas();
        initView();
    }

    public void initDatas(){
        mDatas = new ArrayList<>();
        for (int i = 'A'; i < 'Z'; i++) {
            mDatas.add((char)i+"");
        }
    }

    public void initView(){
        rv = (RecyclerView) findViewById(R.id.id_recycler);
        adapter = new MyAdapter(getApplicationContext(),mDatas);

        LinearLayoutManager manager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);//ListView
        GridLayoutManager gm = new GridLayoutManager(this,3);//GridView
        StaggeredGridLayoutManager sgm = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);//瀑布流
        //这里的点击事件是我们自己在adapter中定义的接口,因为RecycleView的点击事件是在adapter中,所以我们要对外提供一个接口
        adapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this,"点击事件",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemLongClick(View view, int position) {
                Toast.makeText(MainActivity.this,"长按点击事件"+position,Toast.LENGTH_SHORT).show();
            }
        });
        //这里是定义分割线,如果不需要分割线,可以不用添加addItemDecoration
        rv.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
        rv.setLayoutManager(manager);
        rv.setAdapter(adapter);

    }
}
2、Adapter
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    private Context mContext;
    private LayoutInflater mInflater;
    private ArrayList<String> mDatas;

    public MyAdapter(Context context,ArrayList<String> mDatas){
        this.mContext = context;
        this.mDatas = mDatas;
        mInflater = LayoutInflater.from(mContext);
    }

    //对外提供的点击接口
    public interface OnItemClickListener{
        void onItemClick(View view,int position);
        void onItemLongClick(View view,int position);
    }

    private OnItemClickListener mItemClickListener;
    public void setOnItemClickListener(OnItemClickListener listener){
        this.mItemClickListener = listener;
    }

    /**
     * 创建viewHolder
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //这里我们都不需要进行类似于ListView中convertView的复用处理,因为在RecycleView的底层已经对复用进行过处理
        View view = mInflater.inflate(R.layout.item_text,parent,false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    /**
     * 绑定ViewHolder
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        holder.tv.setText(mDatas.get(position));
        final int pos = holder.getLayoutPosition();
        //holder.tv.setHeight(300+( pos % 2 ) * 30 );瀑布流时显示大小不同的item布局
        if(mItemClickListener != null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mItemClickListener.onItemClick(holder.itemView,pos);
                }
            });

            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mItemClickListener.onItemLongClick(holder.itemView,pos);
                    return true;//返回true,将点击的动作事件消费掉,防止点击事件和长按事件重复执行
                }
            });
        }
    }

    /**
     * recyclerView的数量
     * @return
     */
    @Override
    public int getItemCount() {
        return mDatas.size();
    }


    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }
}

class MyViewHolder extends RecyclerView.ViewHolder{

    TextView tv;

    public MyViewHolder(View itemView) {
        super(itemView);

        tv = (TextView) itemView.findViewById(R.id.tv);
    }

}
3、在使用RecycleView中,分割线需要自行定义,不像lsitView中那么简单,不过已经有人在github上提供了定义好的,我们可以直接使用,然后使用Shape来自定义自己需要的分割线的颜色和大小
public class DividerItemDecoration extends RecyclerView.ItemDecoration
{

    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;



    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation)
    {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation)
    {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST)
        {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent)
    {
        Log.v("recyclerview - itemdecoration", "onDraw()");
         if (mOrientation == VERTICAL_LIST) {
                drawVertical(c, parent);
            } else {
                drawHorizontal(c, parent);
            }
    }

    public void drawVertical(Canvas c, RecyclerView parent)
    {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();

        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);
            RecyclerView v = new RecyclerView(
                    parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent)
    {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        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 left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
            RecyclerView parent)
    {
        if (mOrientation == VERTICAL_LIST)
        {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

默认使用的是默认的分割线,如果需要自定义,需要定义shape,并在style的主题中,添加item属性

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <size android:height="4dp"/>
    <solid android:color="#ffff00"/>

</shape>

主题中的属性

<!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        //上面3个是默认的属性,下面的是分割线的属性,引用的是我们自定义的分割线,因为在DividerItemDecoration这个类中,我们的数组属性使用的是默认的listDivider,所以这里的名字必须一致
        <item name="android:listDivider">@drawable/divider_line</item>
    </style>