关闭

总结一下这两天所学RecyclerView

208人阅读 评论(0) 收藏 举报
分类:
转载自:http://blog.csdn.net/wxj1018/article/details/51531838

RecycleView学习总结复习篇

                 recyclerView是android5.0之后推出的一款新的View布局,功能相较于ListView有过之而无不及,相信在以后的学习和工作中都将可能会用上,这两天自己在边看边学其中功能与各种效果,现来博客与诸君分享,也为日后自己复习设下渠道。奋斗

       首先,我们了解一下为什么要叫做RecyclerView?
它不关心Item是否显示在正确位置,如何显示;不关心Item间如何分割;不关注Item增加和删除的动画效果;仅仅关注如何回收和服用View(即英文Recycle的译义)。
那可能有人要问了,这些都是View里比较重要的且频繁使用的属性和效果,都不关心的话,如何做到控制和实现呢?其实,不必担心,我们可以通过LayoutManager来实现Item的显示,ItemDecoration来自定义Item之间的分割线,以及ItemAnimator来完成Item增加和删除时所需要的各种动画(下面的文章会详细介绍)。所以它的功能还是很强大的,值得我们深入研究!

        知道了RecyclerView的概念,我们来大体了解一下它具备的功能:
1.ListView
2.GridView
3.横向ListView
4.横向GridView
5.瀑布流
6.定制Item增加和删除动画
大致为以上功能,是不是挺强大的。生气

工欲善其事必先利其器,下面给出2个需要使用到的链接:
github上recyclerviewItemDecoration原地址


github/上recyclerview动画效果集合原地址


下面进入今天的主题:
由于我们的工程依赖android.support.v7包里的recyclerViewjar包,建立工程时要找到你的sdk存放路径的extras/android/support/v7/recyclerview/libs文件目录下的jar包拷贝到工程目录libs下,才能实现全部功能!

首先我们要首先ListView,写两个方法:initViews();initDatas();
[java] view plain copy
 print?
  1. private void initDatas() {  
  2.         mDatas = new ArrayList<String>();  
  3.         for (int i = 'A'; i <= 'z'; i++) {  
  4.             mDatas.add("" + (char) i);  
  5.         }  
  6.   
  7.     }  
  8.   
  9.     private void initViews() {  
  10.         mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);  
  11.   
  12.     }  
[html] view plain copy
 print?
  1. <android.support.v7.widget.RecyclerView  
  2.         android:id="@+id/id_recyclerview"  
  3.         android:layout_width="wrap_content"  
  4.         android:layout_height="wrap_content">  
  5.           
  6.     </android.support.v7.widget.RecyclerView>  
这两个方法用来创建View和存放数据。这里我放的是A-z。
然后创一个SimpleAdapter来适配主界面。这里需要注意的是要继承RecyclerView.Adapter<MyViewHolder> ,以自己写的MyViewHolder类作为泛型,才能对recycleView里的Item进行配置。
[java] view plain copy
 print?
  1. class MyViewHolder extends ViewHolder {  
  2.   
  3.     TextView tv;  
  4.   
  5.     public MyViewHolder(View arg0) {  
  6.         super(arg0);  
  7.         tv = (TextView) arg0.findViewById(R.id.id_tv);  
  8.     }  
这里我就给每个Item一个TextView,然后通过我们自己的ViewHolder来初始化它。
另外还要重写父类的方法:
[java] view plain copy
 print?
  1.     @Override  
  2.     public int getItemCount() {  
  3.         return mDatas.size();  
  4.     }  
  5.   
  6.     @Override  
  7.     public void onBindViewHolder(final MyViewHolder holder, final int pos) {  
  8.         holder.tv.setText(mDatas.get(pos));  
  9.   
  10.         // click  
  11.         setUpItemEvent(holder);  
  12.     }  
  13. @Override  
  14.     public MyViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) {  
  15.         View view = mInflater.inflate(R.layout.item_simple_textview, arg0, false);  
  16.         MyViewHolder viewHolder = new MyViewHolder(view);  
  17.         return viewHolder;  
  18.     }  
这里主要关注第二个和第三个方法,顾名思义就是绑定ViewHolder和创建Viewholder,
绑定里用位置来设置Item内Text显示的文字,setUpItemEvent(holder);这个方法后面会讲到大家先忽略。然后Create方法里就是初始化View工作,要创建一个item_simple_textview布局文件,里面只放了一个TextView这里我就不做过多赘述,最后返回我们的viewHolder。别忘了做绑定,
mAdapter = new SimpleAdapter(this, mDatas);
mRecyclerView.setAdapter(mAdapter);
还要给布局设置一个管理器:
[java] view plain copy
 print?
  1. // 设置recyclerview的布局管理  
  2.         LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);  
  3.         mRecyclerView.setLayoutManager(layoutManager);  

然而此时我们运行程序会发现虽然ListView正常展示了,可是Item直接并没有分割。

看起来很不舒服,接下来,我们就完成自定义分割线的工作。
由于RecyclerView自身并不能为Item添加分割线,所以我们采用外部开源文件的方法叫做DividerItemDecoration,该方法可以在正文开篇的地址里找到并下载。
[java] view plain copy
 print?
  1. // 设置recyclerview的Item分割线,通过抽象类来控制  
  2. mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));  
这里给Item加一个垂直方向的默认的分割线。(稍后说下自定义)可以得到如下效果

但是,如果默认的分割线不合你的胃口,你完全可以自定义你想要的分割线样式。这就需要我们对开源代码进行简单的分析!
[java] view plain copy
 print?
  1. public DividerItemDecoration(Context context, int orientation)  
  2.     {  
  3.         final TypedArray a = context.obtainStyledAttributes(ATTRS);  
  4.         mDivider = a.getDrawable(0);  
  5.         a.recycle();  
  6.         setOrientation(orientation);  
  7.     }  
这是DividerItemDecoration类的构造方法,从中我们不难看出a对象是从context.obtainStyledAttributes(ATTRS);中获取到的,也就是说从theme中可以得到,这样我们就可以自己定义一个shape放入theme里,就可以给方法查找和调用了。
[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:shape="rectangle" >  
  4.   
  5.     <size android:height="4dp" />  
  6.   
  7.     <gradient  
  8.         android:centerColor="#ff00ff00"  
  9.         android:endColor="#ff0000ff"  
  10.         android:startColor="#ffff0000" />  
  11.   
  12. </shape>  
这里我们写了一个4dp高度的矩形,中间有三种颜色的渐变来作为我们的分割线。
然后由于我使用的SDK是6.0版本,所以讲它放入values-v14包里。
[html] view plain copy
 print?
  1. <resources>  
  2.   
  3.     <!--  
  4.         Base application theme for API 14+. This theme completely replaces  
  5.         AppBaseTheme from BOTH res/values/styles.xml and  
  6.         res/values-v11/styles.xml on API 14+ devices.  
  7.     -->  
  8.     <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">  
  9.         <!-- API 14 theme customizations can go here. -->  
  10.         <span style="background-color: rgb(255, 0, 0);"><!--  <item name="android:listDiveder">@drawable/divider</item>--></span>  
  11.     </style>  
  12.   
  13. </resources>  
然后再次运行程序,就可以得到我们想要的效果。


到这里我们的ListView差不多就实现了。接下来说明一下各自布局的切换使用。
-------------------------------------------------------------------------------------------------------------------


我们用menu里的item来实现不同布局的切换!
进入main.xml添加三个Item
[html] view plain copy
 print?
  1. <item  
  2.     android:id="@+id/action_listView"  
  3.     android:orderInCategory="100"  
  4.     android:showAsAction="never"  
  5.     android:title="ListView"/>  
  6. <item  
  7.     android:id="@+id/action_gridView"  
  8.     android:orderInCategory="100"  
  9.     android:showAsAction="never"  
  10.     android:title="gridView"/>  
  11. <item  
  12.     android:id="@+id/action_staggered"  
  13.     android:orderInCategory="100"  
  14.     android:showAsAction="never"  
  15.     android:title="Staggered"/>  
分别代表ListView、GridView、瀑布流布局。然后根据id来设置点击到不同Item时显示的布局样式。
[java] view plain copy
 print?
  1. @Override  
  2.     public boolean onOptionsItemSelected(MenuItem item) {  
  3.         // Handle action bar item clicks here. The action bar will  
  4.         // automatically handle clicks on the Home/Up button, so long  
  5.         // as you specify a parent activity in AndroidManifest.xml.  
  6.         int id = item.getItemId();  
  7.         switch (id) {  
  8.         case R.id.action_add:  
  9.             mAdapter.addData(1);  
  10.             break;  
  11.         case R.id.action_delete:  
  12.             mAdapter.deleteData(1);  
  13.             break;  
  14.         case R.id.action_listView:  
  15.             mRecyclerView.setLayoutManager(new LinearLayoutManager(this));  
  16.             break;  
  17.         case R.id.action_gridView:  
  18.             mRecyclerView.setLayoutManager(new GridLayoutManager(this3));  
  19.             break;  
  20.         case R.id.action_staggered:  
  21.             Intent intent = new Intent(this, StaggeredActivity.class);  
  22.             startActivity(intent);  
  23.             break;  
  24.         default:  
  25.             break;  
  26.         }  
  27.         return false;  
  28.     }  

同样,上面两个后面再做解释,先看后面三个选项。每当不同id被选中时,我们给予recyclerView不同的LayoutManager,这样它就显示不同的布局了!由于GridView和ListView是继承自同一父类,所以他们之间转化不要开启新的Activity而瀑布流布局就需要开启新Acitivity来显示,我们采用显式Intent切换。


GridView就这样了,比较简单,下面我们主要研究一下瀑布流的代码。

我们把MainActivity和SimpleAdapter都拷贝一份,改名为StaggeredActivity和StaggeredAdapter。
为了防止代码复写的麻烦,直接在SimpleAdapter里提供一个回调方法,供StaggeredAdapter使用,实现点击和长按事件。
[java] view plain copy
 print?
  1. // 设置一个接口回调,给Item绑定一个点击事件  
  2.     public interface OnItemClickListener {  
  3.         void onItemClick(View view, int position);  
  4.   
  5.         void onItemLongClick(View view, int position);  
  6.     }  
  7.   
  8.     private OnItemClickListener onItemClickListener;  
  9.   
  10.     public void setOnItemClickListener(OnItemClickListener listener) {  
  11.         this.onItemClickListener = listener;  
  12.     }  
[java] view plain copy
 print?
  1. protected void setUpItemEvent(final MyViewHolder holder) {  
  2.         if (onItemClickListener != null) {  
  3.             holder.itemView.setOnClickListener(new OnClickListener() {  
  4.   
  5.                 @Override  
  6.                 public void onClick(View v) {  
  7.   
  8.                     int layoutPosition = holder.getLayoutPosition();  
  9.                     onItemClickListener.onItemClick(holder.itemView, layoutPosition);  
  10.   
  11.                 }  
  12.             });  
  13.         }  
  14.         // longclick  
  15.         holder.itemView.setOnLongClickListener(new OnLongClickListener() {  
  16.   
  17.             @Override  
  18.             public boolean onLongClick(View v) {  
  19.                 int layoutPosition = holder.getLayoutPosition();  
  20.                 onItemClickListener.onItemLongClick(holder.itemView, layoutPosition);  
  21.                 return false;  
  22.             }  
  23.         });  
  24.     }  
这样处理的话,就可以让StaggeredAdapter的代码更加简洁:
[java] view plain copy
 print?
  1. public class StaggeredAdapter extends SimpleAdapter {  
  2.   
  3.     private LayoutInflater mInflater;  
  4.     private Context mContext;  
  5.     private List<String> mDatas;  
  6.     private List<Integer> mHeight;  
  7.   
  8.     public StaggeredAdapter(Context context, List<String> datas) {  
  9.         super(context, datas);  
  10.   
  11.         mHeight = new ArrayList<Integer>();  
  12.         for (int i = 0; i < mDatas.size(); i++) {  
  13.             mHeight.add((int) (100 + Math.random() * 300));  
  14.         }  
  15.     }  
  16.   
  17.     @Override  
  18.     public void onBindViewHolder(MyViewHolder holder, int pos) {  
  19.   
  20.         LayoutParams lp = (LayoutParams) holder.itemView.getLayoutParams();  
  21.         lp.height = mHeight.get(pos);  
  22.         holder.itemView.setLayoutParams(lp);  
  23.   
  24.         holder.tv.setText(mDatas.get(pos));  
  25.         setUpItemEvent(holder);  
  26.   
  27.     }  
  28.   
  29. }  

把height做一个随机数处理,就可以得到瀑布流那样不规则的分布布局。然后通过LayoutParams和height进行绑定,就可以动态的设置item的高度了。setUpItemEvent就是响应点击和长按事件。效果如下:


关于Item增加和删除的动画:
在menu里加入两个图标,增加和删除,对应前面代码所示的switch方法内add和delete方法。代码如下:
[java] view plain copy
 print?
  1. public void addData(int pos) {  
  2.         mDatas.add(pos, "Insert one");  
  3.         notifyItemInserted(pos);  
  4.     }  
  5.   
  6.     public void deleteData(int pos) {  
  7.         mDatas.remove(pos);  
  8.         notifyItemRemoved(pos);  
  9.     }  
注意:这里使用了notifyItemInserted和notifyItemRemoved两个方法,它会导致点击加入或者删除Item后,新增的Item和删除的Item后面那个Item的postion不变,因为他只notify了增加和移除,并没有重绘View,所以后面代码里用getParamPosition()方法来得到View所显示的Item的动态位置,就不会造成多个position相同的情况。

[java] view plain copy
 print?
  1. mRecyclerView.setItemAnimator(new DefaultItemAnimator());  
这里我使用的默认的动画效果,大家可以去开篇给出的链接下载动画效果源码,实现各种炫酷的动画!

-------------------------------------------------------------------------------------------------------------------


好了,基本的功能已经介绍的差不多了,更多的炫酷动画和花式布局,需要靠我们更多的去研究和学习!本人也只是小白阶段,跟着视频学习完写个博客记录一下学习成果,方便以后的复习同时也能给需要的人带来一点参考和建议吧。共勉!
1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:101435次
    • 积分:1253
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:171篇
    • 译文:0篇
    • 评论:10条
    最新评论