总结一下这两天所学RecyclerView
2016-05-29 13:57
288 查看
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个需要使用到的链接:
https://gist.github.com/alexfu/0f464fc3742f134ccd1e
github上recyclerviewItemDecoration原地址
https://github.com/gabrielemariotti/RecyclerViewItemAnimators
github/上recyclerview动画效果集合原地址
下面进入今天的主题:
由于我们的工程依赖android.support.v7包里的recyclerViewjar包,建立工程时要找到你的sdk存放路径的extras/android/support/v7/recyclerview/libs文件目录下的jar包拷贝到工程目录libs下,才能实现全部功能!
首先我们要首先ListView,写两个方法:initViews();initDatas();
private void initDatas() { mDatas = new ArrayList<String>(); for (int i = 'A'; i <= 'z'; i++) { mDatas.add("" + (char) i); } } private void initViews() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); }
<android.support.v7.widget.RecyclerView android:id="@+id/id_recyclerview" android:layout_width="wrap_content" android:layout_height="wrap_content"> </android.support.v7.widget.RecyclerView>这两个方法用来创建View和存放数据。这里我放的是A-z。
然后创一个SimpleAdapter来适配主界面。这里需要注意的是要继承RecyclerView.Adapter<MyViewHolder> ,以自己写的MyViewHolder类作为泛型,才能对recycleView里的Item进行配置。
class MyViewHolder extends ViewHolder { TextView tv; public MyViewHolder(View arg0) { super(arg0); tv = (TextView) arg0.findViewById(R.id.id_tv); }这里我就给每个Item一个TextView,然后通过我们自己的ViewHolder来初始化它。
另外还要重写父类的方法:
@Override public int getItemCount() { return mDatas.size(); } @Override public void onBindViewHolder(final MyViewHolder holder, final int pos) { holder.tv.setText(mDatas.get(pos)); // click setUpItemEvent(holder); } @Override public MyViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) { View view = mInflater.inflate(R.layout.item_simple_textview, arg0, false); MyViewHolder viewHolder = new MyViewHolder(view); return viewHolder; }这里主要关注第二个和第三个方法,顾名思义就是绑定ViewHolder和创建Viewholder,
绑定里用位置来设置Item内Text显示的文字,setUpItemEvent(holder);这个方法后面会讲到大家先忽略。然后Create方法里就是初始化View工作,要创建一个item_simple_textview布局文件,里面只放了一个TextView这里我就不做过多赘述,最后返回我们的viewHolder。别忘了做绑定,
mAdapter = new SimpleAdapter(this, mDatas);
mRecyclerView.setAdapter(mAdapter);
还要给布局设置一个管理器:
// 设置recyclerview的布局管理 LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); mRecyclerView.setLayoutManager(layoutManager);
然而此时我们运行程序会发现虽然ListView正常展示了,可是Item直接并没有分割。
看起来很不舒服,接下来,我们就完成自定义分割线的工作。
由于RecyclerView自身并不能为Item添加分割线,所以我们采用外部开源文件的方法叫做DividerItemDecoration,该方法可以在正文开篇的地址里找到并下载。
// 设置recyclerview的Item分割线,通过抽象类来控制 mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));这里给Item加一个垂直方向的默认的分割线。(稍后说下自定义)可以得到如下效果
但是,如果默认的分割线不合你的胃口,你完全可以自定义你想要的分割线样式。这就需要我们对开源代码进行简单的分析!
public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); }这是DividerItemDecoration类的构造方法,从中我们不难看出a对象是从context.obtainStyledAttributes(ATTRS);中获取到的,也就是说从theme中可以得到,这样我们就可以自己定义一个shape放入theme里,就可以给方法查找和调用了。
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <size android:height="4dp" /> <gradient android:centerColor="#ff00ff00" android:endColor="#ff0000ff" android:startColor="#ffff0000" /> </shape>这里我们写了一个4dp高度的矩形,中间有三种颜色的渐变来作为我们的分割线。
然后由于我使用的SDK是6.0版本,所以讲它放入values-v14包里。
<resources> <!-- Base application theme for API 14+. This theme completely replaces AppBaseTheme from BOTH res/values/styles.xml and res/values-v11/styles.xml on API 14+ devices. --> <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <!-- API 14 theme customizations can go here. --> <span style="background-color: rgb(255, 0, 0);"><!-- <item name="android:listDiveder">@drawable/divider</item>--></span> </style> </resources>然后再次运行程序,就可以得到我们想要的效果。
到这里我们的ListView差不多就实现了。接下来说明一下各自布局的切换使用。
-------------------------------------------------------------------------------------------------------------------
我们用menu里的item来实现不同布局的切换!
进入main.xml添加三个Item
<item android:id="@+id/action_listView" android:orderInCategory="100" android:showAsAction="never" android:title="ListView"/> <item android:id="@+id/action_gridView" android:orderInCategory="100" android:showAsAction="never" android:title="gridView"/> <item android:id="@+id/action_staggered" android:orderInCategory="100" android:showAsAction="never" android:title="Staggered"/>分别代表ListView、GridView、瀑布流布局。然后根据id来设置点击到不同Item时显示的布局样式。
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); switch (id) { case R.id.action_add: mAdapter.addData(1); break; case R.id.action_delete: mAdapter.deleteData(1); break; case R.id.action_listView: mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); break; case R.id.action_gridView: mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3)); break; case R.id.action_staggered: Intent intent = new Intent(this, StaggeredActivity.class); startActivity(intent); break; default: break; } return false; }
同样,上面两个后面再做解释,先看后面三个选项。每当不同id被选中时,我们给予recyclerView不同的LayoutManager,这样它就显示不同的布局了!由于GridView和ListView是继承自同一父类,所以他们之间转化不要开启新的Activity而瀑布流布局就需要开启新Acitivity来显示,我们采用显式Intent切换。
GridView就这样了,比较简单,下面我们主要研究一下瀑布流的代码。
我们把MainActivity和SimpleAdapter都拷贝一份,改名为StaggeredActivity和StaggeredAdapter。
为了防止代码复写的麻烦,直接在SimpleAdapter里提供一个回调方法,供StaggeredAdapter使用,实现点击和长按事件。
// 设置一个接口回调,给Item绑定一个点击事件 public interface OnItemClickListener { void onItemClick(View view, int position); void onItemLongClick(View view, int position); } private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener listener) { this.onItemClickListener = listener; }
protected void setUpItemEvent(final MyViewHolder holder) { if (onItemClickListener != null) { holder.itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int layoutPosition = holder.getLayoutPosition(); onItemClickListener.onItemClick(holder.itemView, layoutPosition); } }); } // longclick holder.itemView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { int layoutPosition = holder.getLayoutPosition(); onItemClickListener.onItemLongClick(holder.itemView, layoutPosition); return false; } }); }这样处理的话,就可以让StaggeredAdapter的代码更加简洁:
public class StaggeredAdapter extends SimpleAdapter { private LayoutInflater mInflater; private Context mContext; private List<String> mDatas; private List<Integer> mHeight; public StaggeredAdapter(Context context, List<String> datas) { super(context, datas); mHeight = new ArrayList<Integer>(); for (int i = 0; i < mDatas.size(); i++) { mHeight.add((int) (100 + Math.random() * 300)); } } @Override public void onBindViewHolder(MyViewHolder holder, int pos) { LayoutParams lp = (LayoutParams) holder.itemView.getLayoutParams(); lp.height = mHeight.get(pos); holder.itemView.setLayoutParams(lp); holder.tv.setText(mDatas.get(pos)); setUpItemEvent(holder); } }
把height做一个随机数处理,就可以得到瀑布流那样不规则的分布布局。然后通过LayoutParams和height进行绑定,就可以动态的设置item的高度了。setUpItemEvent就是响应点击和长按事件。效果如下:
关于Item增加和删除的动画:
在menu里加入两个图标,增加和删除,对应前面代码所示的switch方法内add和delete方法。代码如下:
public void addData(int pos) { mDatas.add(pos, "Insert one"); notifyItemInserted(pos); } public void deleteData(int pos) { mDatas.remove(pos); notifyItemRemoved(pos); }注意:这里使用了notifyItemInserted和notifyItemRemoved两个方法,它会导致点击加入或者删除Item后,新增的Item和删除的Item后面那个Item的postion不变,因为他只notify了增加和移除,并没有重绘View,所以后面代码里用getParamPosition()方法来得到View所显示的Item的动态位置,就不会造成多个position相同的情况。
mRecyclerView.setItemAnimator(new DefaultItemAnimator());这里我使用的默认的动画效果,大家可以去开篇给出的链接下载动画效果源码,实现各种炫酷的动画!
-------------------------------------------------------------------------------------------------------------------
好了,基本的功能已经介绍的差不多了,更多的炫酷动画和花式布局,需要靠我们更多的去研究和学习!本人也只是小白阶段,跟着视频学习完写个博客记录一下学习成果,方便以后的复习同时也能给需要的人带来一点参考和建议吧。共勉!
相关文章推荐
- 第14课:Spark Streaming源码解读之State管理之updateStateByKey和mapWithState解密
- Java Web中涉及的编解码
- 一位有故事的测试者对开发者的忠告
- FFMPEG
- 运算符||无法应用于bool和string类型的操作数
- css3 -- 渐变
- 第十三周进度条
- python 正则表达式
- FreeRTOS内核详解----Queue
- Android中DatePicker控件用法解析
- CXF客户端异常
- Struts2系列——struts2的result
- imx6q开发环境的搭建(ubuntu+yocoto)
- 吉香缘公司 Y7 跳跃
- 关系数据库及异常处理
- hdu_2089_不要62(数位DP)
- POJ1005 I Think I Need a Houseboat【π】
- hdu_2089_不要62(数位DP)
- task
- JAVA中获取工程路径的方法