recyclerViewViewAndroid学习

RecyclerView完全解析(一)——基本使用

2017-07-02  本文已影响2179人  _猜火车_
特别声明:

一、前言

1. RecyclerView控件的基本使用,包括基础,进阶,高级部分,动画之类
2. RecyclerView控件的实战实例
3. RecyclerView控件集合AA(Android Annotations)注入框架实例

FastDev4Android框架项目地址:https://github.com/jiangqqlmj/FastDev4Android

二、RecyclerView基本介绍:

1. 采用LayoutManager来处理Item的布局
2. 提供Item操作的默认动画,例如在增加或者删除item的时候

Adapter:继承自RecyclerView.Adapetr类,主要用来将数据和布局item进行绑定。
LayoutManager:布局管理器,设置每一项view在RecyclerView中的位置布局以及控件item view的显示或者隐藏。当View重用或者回收的时候,LayoutManger都会向Adapter来请求新的数据来进行替换原来数据的内容。这种回收重用的机制可以提供性能,避免创建很多的view或者是频繁的调用findViewById方法。这种机制和ListView还是很相似的。

1. LinearLayoutManager:线性布局,横向或者纵向滑动列表
2. GridLayoutManager:表格布局
3. StaggeredGridLayoutManager:流式布局,例如瀑布流效果

RecyclerView对于Item的添加和删除是默认开启动画的。我们当然也可以通过RecyclerView.ItemAnimator类定制动画,然后通过RecyclerView.setItemAnimator()方法来进行使用。

类名 说明
RecyclerView.Adapter 可以托管数据集合,为每一项Item创建视图并且绑定数据
RecyclerView.ViewHolder 承载Item视图的子布局
RecyclerView.LayoutManager 负责Item视图的布局的显示管理
RecyclerView.ItemDecoration 给每一项Item视图添加子View,例如可以进行画分隔线之类的
RecyclerView.ItemAnimator 负责处理数据添加或者删除时候的动画效果

三、RecyclerView基本实现:

1、添加库依赖:
dependencies {  
   …….  
    compile'com.android.support:recyclerview-v7:23.1.1'  
}    
2、新建布局,引入RecyclerView控件:
<?xmlversionxmlversion="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:androidLinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"android:layout_width="match_parent"  
   android:layout_height="match_parent">  
    <includelayoutincludelayout="@layout/common_top_bar_layout"/>  
   
    <android.support.v7.widget.RecyclerView  
       android:id="@+id/recyclerView_one"  
       android:layout_width="match_parent"  
       android:layout_height="match_parent"  
        android:scrollbars="vertical"  
       ></android.support.v7.widget.RecyclerView>  
</LinearLayout>  
3、在Activity中获取RecyclerView控件然后进行设置LayoutManger以及Adapter即可,和ListView的写法有点类似:
public class RecyclerViewTestActivity extends AppCompatActivity {
    
    private RecyclerView recyclerView_one;
    private RecyclerView.Adapter mAdapter;
    private LinearLayoutManager mLayoutManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //开始设置RecyclerView
        recyclerView_one=(RecyclerView)this.findViewById(R.id.recyclerView);
        //设置固定大小
        recyclerView_one.setHasFixedSize(true);
        //创建线性布局
        mLayoutManager = new LinearLayoutManager(this);
        //垂直方向
        mLayoutManager.setOrientation(OrientationHelper.VERTICAL);
        //给RecyclerView设置布局管理器
        recyclerView_one.setLayoutManager(mLayoutManager);
        //创建适配器,并且设置
        mAdapter = new TestRecyclerAdapter(this);
        recyclerView_one.setAdapter(mAdapter);
    }
    
}
4、自定义一个适配器来进行创建item view以及绑定数据
public class TestRecyclerAdapter extends RecyclerView.Adapter<TestRecyclerAdapter.ViewHolder>{

    private LayoutInflater mInflater;
    private String[] mTitles=null;

    public TestRecyclerAdapter(Context context){
        this.mInflater=LayoutInflater.from(context);
        this.mTitles=new String[20];
        for (int i=0;i<20;i++){
            int index=i+1;
            mTitles[i]="item"+index;
        }
    }
    /**
     * item显示类型
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=mInflater.inflate(R.layout.item_recycler_layout,parent,false);
        //view.setBackgroundColor(Color.RED);
        ViewHolder viewHolder=new ViewHolder(view);
        return viewHolder;
    }
    /**
     * 数据的绑定显示
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.item_tv.setText(mTitles[position]);
    }

    @Override
    public int getItemCount() {
        return mTitles.length;
    }

    //自定义的ViewHolder,持有每个Item的的所有界面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView item_tv;
        public ViewHolder(View view){
            super(view);
            item_tv = (TextView)view.findViewById(R.id.item_tv);
        }
    }
}

这个自定义Adapter和我们在使用Listview时候的Adapter相比还是有点不太一样的,首先这边我们需要继承RecyclerView.Adaper类,然后实现两个重要的方法onBindViewHodler()以及onCreateViewHolder(),这边我们看出来区别,使用RecyclerView控件我们就可以把Item View视图创建和数据绑定这两步进行分来进行管理,用法就更加方便而且灵活了,并且我们可以定制打造千变万化的布局。同时这边我们还需要创建一个ViewHolder类,该类必须继承自RecyclerView.ViewHolder类,现在Google也要求我们必须要实现ViewHolder来承载Item的视图。

mLayoutManager.setOrientation(OrientationHelper.HORIZONTAL);  

运行效果如下:


那么另外两种内置的布局如下:
GridLayoutManager girdLayoutManager=new GridLayoutManager(this,4);  
 recyclerView_one.setLayoutManager(girdLayoutManager);  

运行效果如下:


StaggeredGridLayoutManager staggeredGridLayoutManager=new   StaggeredGridLayoutManager(2,OrientationHelper.VERTICAL);  
  recyclerView_one.setLayoutManager(staggeredGridLayoutManager);  

实现的是瀑布流的效果

四、RecyclerView分隔线实现(ItemDecoration):

RecyclerView.ItemDecoration 给每一项Item视图添加子View,可以进行画分隔线之类的东西
public static abstract class ItemDecoration {  
        public void onDraw(Canvas c,RecyclerView parent, State state) {  
            onDraw(c, parent);  
        }  
        public void onDrawOver(Canvas c,RecyclerView parent, State state) {  
            onDrawOver(c, parent);  
        }  
        public void getItemOffsets(RectoutRect, View view, RecyclerView parent, State state) {  
            getItemOffsets(outRect,((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),  
                    parent);  
        }  
    }  
public class TestDecoration extends RecyclerView.ItemDecoration {  
    //采用系统内置的风格的分割线  
    private static final int[] attrs=newint[]{android.R.attr.listDivider};  
    private Drawable mDivider;  
   
    public TestDecoration(Context context) {  
        TypedArray typedArray=context.obtainStyledAttributes(attrs);  
        mDivider=typedArray.getDrawable(0);  
    }  
   
    /** 
     * 进行自定义绘制 
     * @param c 
     * @param parent 
     * @param state 
     */  
    @Override  
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  
        int top=parent.getPaddingTop();  
        intbottom=parent.getHeight()-parent.getPaddingBottom();  
        int childCount=parent.getChildCount();  
        for(int i=0;i<childCount;i++){  
            View child=parent.getChildAt(i);  
            RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();  
            intleft=child.getRight()+layoutParams.rightMargin;  
            intright=left+mDivider.getIntrinsicWidth();  
            mDivider.setBounds(left,top,right,bottom);  
            mDivider.draw(c);  
        }  
    }  
   
    @Override  
    public void getItemOffsets(Rect outRect,View view, RecyclerView parent, RecyclerView.State state) {  
       outRect.set(0,0,mDivider.getIntrinsicWidth(),0);  
    }  
}  
  • 我这边实例中采用系统主题(android.R.attr.listDivider)来设置成分隔线的,然后来获取尺寸,位置进行setBound(),绘制,接着通过outRect.set()来设置绘制整个区域范围,最后不要忘记往RecyclerView中设置该自定义的分割线:
//添加分割线
recyclerView_one.addItemDecoration(newTestDecoration(this));  
/** 
 * 当前类注释:改进之后的自定义Decoration分割线 
 */  
public class AdvanceDecoration extends RecyclerView.ItemDecoration{  
    //采用系统内置的风格的分割线  
    private static final int[] attrs=newint[]{android.R.attr.listDivider};  
    private Drawable mDivider;  
    private int orientation;  
    public AdvanceDecoration(Contextcontext,int orientation) {  
        TypedArray typedArray=context.obtainStyledAttributes(attrs);  
        mDivider=typedArray.getDrawable(0);  
        typedArray.recycle();  
        this.orientation=orientation;  
    }  
    @Override  
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  
                 drawHDeraction(c,parent);  
                 drawVDeraction(c,parent);  
    }  
    /** 
     * 绘制水平方向的分割线 
     * @param c 
     * @param parent 
     */  
    private void drawHDeraction(Canvas c,RecyclerView parent){  
        int left=parent.getPaddingLeft();  
        intright=parent.getWidth()-parent.getPaddingRight();  
        int childCount=parent.getChildCount();  
        for(int i=0;i<childCount;i++){  
            View child=parent.getChildAt(i);  
            RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();  
            inttop=child.getBottom()+layoutParams.bottomMargin;  
            intbottom=top+mDivider.getIntrinsicHeight();  
           mDivider.setBounds(left,top,right,bottom);  
            mDivider.draw(c);  
        }  
    }  
    /** 
     * 绘制垂直方向的分割线 
     * @param c 
     * @param parent 
     */  
    private void drawVDeraction(Canvas c,RecyclerView parent){  
        int top=parent.getPaddingTop();  
        intbottom=parent.getHeight()-parent.getPaddingBottom();  
        int childCount=parent.getChildCount();  
        for(int i=0;i<childCount;i++){  
            View child=parent.getChildAt(i);  
            RecyclerView.LayoutParamsla youtParams=(RecyclerView.LayoutParams)child.getLayoutParams();  
            intleft=child.getRight()+layoutParams.rightMargin;  
            intright=left+mDivider.getIntrinsicWidth();  
           mDivider.setBounds(left,top,right,bottom);  
            mDivider.draw(c);  
        }  
    }  
    @Override  
    public void getItemOffsets(Rect outRect,View view, RecyclerView parent, RecyclerView.State state) {  
       if(OrientationHelper.HORIZONTAL==orientation){  
            outRect.set(0, 0,mDivider.getIntrinsicWidth(), 0);  
        }else {  
            outRect.set(0, 0, 0,mDivider.getIntrinsicHeight());  
        }  
    }  
}  
  • 改良之后的自定义分割器的构造函数中新增一个int参数,用来表示横向还是纵向布局,这样我们可以分别来绘制分割线。
recyclerView_one.addItemDecoration(new AdvanceDecoration(this,OrientationHelper.VERTICAL));

五、RecyclerView高级用户(监听事件处理)

public ViewHolder onCreateViewHolder(ViewGroupparent, int viewType) {  
       Viewview=mInflater.inflate(R.layout.item_recycler_layout,parent,false);  
       //这边可以做一些属性设置,甚至事件监听绑定  
       //view.setBackgroundColor(Color.RED);  
       ViewHolder viewHolder=newViewHolder(view);  
       return viewHolder;  
   }  
   /** 
    * 自定义RecyclerView 中item view点击回调方法 
    */  
    interface OnRecyclerItemClickListener{  
        /** 
         * item view 回调方法 
         * @param view  被点击的view 
         * @param position 点击索引 
         */  
        void onItemClick(View view, intposition);  
    }  
public  TestRecyclerAdapter(Contextcontext,OnRecyclerItemClickListener onRecyclerItemClickListener){  
        ……
       this.onRecyclerItemClickListener=onRecyclerItemClickListener;  
    }  
view.setOnClickListener(new View.OnClickListener() {  
         @Override  
         public void onClick(View v) {  
            if(onRecyclerItemClickListener!=null){  
                onRecyclerItemClickListener.onItemClick(view, (int)view.getTag());  
             }  
         }  
   });  

注意:这里的view就是onCreateViewHolder方法里返回的view,完整逻辑大致就是如下的样子:

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View view=mInflater.inflate(R.layout.item_recycler_layout,parent,false);
        //这边可以做一些属性设置,甚至事件监听绑定
        //view.setBackgroundColor(Color.RED);
        ViewHolder viewHolder=new ViewHolder(view);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(onRecyclerItemClickListener!=null){
                    onRecyclerItemClickListener.onItemClick(view, (int)view.getTag());
                }
            }
        });
        return viewHolder;
    }
public voidonBindViewHolder(ViewHolder holder, int position) {  
       holder.item_tv.setText(mTitles[position]);  
       holder.itemView.setTag(position);  
    }  
mAdapter = new TestRecyclerAdapter(this, new TestRecyclerAdapter.OnRecyclerItemClickListener() {  
            @Override  
            public void onItemClick(View view,int position) {  
               Toast.makeText(RecyclerViewTestActivity.this, "点击了第"+position+"项", Toast.LENGTH_SHORT).show();  
            }  
  });  

六、RecyclerView数据添加删除处理

//添加数据  
 public void addItem(String data, int  position) {  
     mTitles.add(position, data);  
     notifyItemInserted(position);  
 }  
 //删除数据  
 public void removeItem(String data) {  
     int position = mTitles.indexOf(data);  
     mTitles.remove(position);  
     notifyItemRemoved(position);  
 }  
//添加数据  
mAdapter.addItem("additem",5);  
//删除数据  
mAdapter.removeItem("item4");  
//添加默认的动画效果  
recyclerView_one.setItemAnimator(new DefaultItemAnimator());  

七、RecyclerView总结

上一篇下一篇

猜你喜欢

热点阅读