RecyclerView

先给大家看一下效果:

这里写图片描述

个人关于RecyclerView的理解

RecyclerView 是Android 版本中新添加的一个用来取代ListView、GridView的SDK,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现不同的效果。

1.RecyclerView特性:
1)Item的显示位置,如何显示,通过LayoutManager设置
2)Item间的分割通过ItemDecoration设置
3)Item增加与删除的动画通过ItemAnimator设置(系统提供一种默认动画效果DefaultItemAnimator,可以自定义动画效果)
4)仅仅关注如何回收与复用view

2.RecyclerView相关的重要类
Adapter、ViewHolder、LayoutManager、ItemDecoration、ItemAnimator

Adapter:包装数据集合并且为每个条目创建视图。
ViewHolder:保存用于显示每个数据条目的子View。
LayoutManager:将每个条目的视图放置于适当的位置。
ItemDecoration:在每个条目的视图的周围或上面绘制一些装饰视图。
ItemAnimator:在条目被添加、移除或者重排序时添加动画效果。

3.RecyclerView的功能
1)竖向listview的风格 (依赖LayoutManager)
2)横向listview的风格 (依赖LayoutManager)
3)竖向gridview的风格 (依赖LayoutManager)
4)横向gridview的风格 (依赖LayoutManager)
5)瀑布流 (依赖LayoutManager)
6)定制Item增加与删除动画 (依赖ItemAnimator)

下面就看一下关于它的简单的使用吧:

添加的依赖: compile ‘com.android.support:recyclerview-v7:21.0.+’

item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_margin="3dp"
    android:background="@drawable/item_selector"
    android:layout_height="72dp">
    <TextView
        android:id="@+id/item_text"
        android:layout_width="72dp"
        android:layout_height="match_parent"
        android:gravity="center"
        />
</RelativeLayout>

activity_main.xml布局:

<LinearLayout 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:background="#22ff0000"
    tools:context=".MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"/>
</LinearLayout>

瀑布流效果的实现和其他效果的实现只是Adapter有一点不一样,先来看一下其它几种效果的实现:

RecyclerView.ViewHolder的基本作用是缓存视图对象;
RecyclerView.Adapter还没有默认实现,以后可能会添加。由于RecyclerView.Adapter是一个抽象类,所以必须要实现以下三个方法:
- public VH onCreateViewHolder(ViewGroup parent, int viewType)
- public void onBindViewHolder(VH holder, int position)
- public int getItemCount()

其中VH是泛型类,当继承RecyclerView.Adapter时需要使用具体的类来替换。RecyclerViewAdapter 的示例代码如下:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{
    protected List<String> mListData;
    private Context mContext;
    public RecyclerViewAdapter(Context context,List<String> datas){
        this.mListData = datas;
        this.mContext = context;
        mLayoutInflater = LayoutInflater.from(mContext);
    }


    //创建ViewHolder
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mLayoutInflater.inflate(R.layout.item,parent,false);
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }
    //绑定ViewHolder
    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        holder.mTextView.setText(mListData.get(position));
    }
    @Override
    public int getItemCount() {
        return mListData.size();
    }
    class ViewHolder extends RecyclerView.ViewHolder{
        TextView mTextView;
        public ViewHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.item_text);
        }
    }
}

RecyclerView的Adapter和之前使用的listview的Adapter还是有相同之处的,所以使用起来并不陌生;

MainActivity.java

mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
//填充数据
mRecyclerViewAdapter = new RecyclerViewAdapter(mContext,mListData);
//设置adapter
mRecyclerView.setAdapter(mRecyclerViewAdapter);
//设置listview垂直如何显示
mLinearLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
//创建默认的线性布局Linearlayout
mRecyclerView.setLayoutManager(mLinearLayoutManager);
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
//添加动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//绘制分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(mContext, DividerItemDecoration.VERTICAL_LIST));
  • RecyclerView.LayoutManager该类负责放置所有的子View到适当位置。该类有一个默认的实现:LinearLayoutManager,当要实现水平或垂直列表时可以使用该类;
  • RecyclerView.ItemAnimator设置动画,可以进行自定义动画;
  • RecyclerView.ItemDecoration设置item之间的分割线,操作如下:

DefaultItemAnimator.java

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) {
        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);
            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);
        }
    }
}

divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:height="2dp"/>
    <gradient android:startColor="#ff00ff00" android:centerColor="#ff0000ff" android:endColor="#ffff0000"/>
</shape>

编写分割线样式

最后操作style.xml:
这里写图片描述
分割线就添加完成了,效果如下:
这里写图片描述
效果还挺不错的吧。一般我们可能不会用到,因为在item中直接添加View比这种方式简单多了,嘻嘻。

完成这些之后,实现其他几种效果就是设置不同的LayoutManager样式了,代码如下:

//ListView
case R.id.action_listview:
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    break;
//GridView
case R.id.action_gridview:
    mRecyclerView.setLayoutManager(new GridLayoutManager(this,3));
    break;
//水平GridVIew
case R.id.action_hor_gridview:
    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(5,StaggeredGridLayoutManager.HORIZONTAL));
    break;

现在我们就完成了垂直、水平的ListView和垂直、水平的GridView的效果了,感觉还不错;

由于RecyclerView没有提供点击事件,所以学要我们自己来实现,代码如下:

//定义接口
public interface OnItemClickListener{
    void onItemClick(View v,int position);
    void onItemLongClick(View v,int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
    this.mOnItemClickListener = listener ;
}

在绑定ViewHolder的时候去触发:

//绑定ViewHolder
 @Override
 public void onBindViewHolder(final ViewHolder holder, final int position) {
     holder.mTextView.setText(mListData.get(position));
     setOnListtener(holder);
 }
 //触发
 protected void setOnListtener(final RecyclerView.ViewHolder holder){

     if(mOnItemClickListener != null){
         holder.itemView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 int layoutPosition = holder.getPosition();
                 mOnItemClickListener.onItemClick(holder.itemView,layoutPosition);
             }
         });
         holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
             @Override
             public boolean onLongClick(View v) {
                 int layoutPosition = holder.getPosition();
                 mOnItemClickListener.onItemLongClick(holder.itemView,layoutPosition);
                 return false;
             }
         });
     }
 }

点击事件:

//点击事件
mRecyclerViewAdapter.setOnItemClickListener(new RecyclerViewAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(View v, int position) {
        Toast.makeText(mContext, "onclick  " + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onItemLongClick(View v, int position) {
        Toast.makeText(mContext, "onlongclick  " + position, Toast.LENGTH_SHORT).show();
    }
});

点击效果就完成了,添加和删除Item效果如下:

//添加布局
public void add(int pos){
    mListData.add(pos,"add"+pos);
    notifyItemInserted(pos);
}
//删除布局
public void delete(int pos){
    mListData.remove(pos);
    notifyItemRemoved(pos);
}

注意:
1.添加item的时候使用notifyItemInserted(position);
移除item的时候使用notifyItemRemoved(position); 而不是notifidatasetchanged();

接下来我们就看看瀑布流的实现

瀑布流的原理就是给每个item重新设置宽和高:
StaggeredRecyclerViewAdapter.java

//绑定ViewHolder
@Override
public void onBindViewHolder(StaggeredRecyclerViewAdapter.ViewHolder holder, int position) {
    LayoutParams lp = holder.itemView.getLayoutParams();
    lp.height = mHeights.get(position);
    holder.itemView.setLayoutParams(lp);

    holder.mTextView.setText(mListData.get(position));
    setOnListtener(holder);
}

再设置显示方式:

mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);

瀑布流的效果就实现了!

RecyclerView最基本的使用就讲完了,大家肯定了解BGARefreshLayout这个刷新控件,下一篇博客我会讲解RecyclerView+BGARefreshLayout实现下拉刷新、自定义上拉加载和侧滑删除的效果,先给大家看一下效果图:

这里写图片描述
还不错吧!

GitHub下载地址:
https://github.com/fengmaolian/RecyclerView

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值