总结一下这两天所学RecyclerView

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();
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());
这里我使用的默认的动画效果,大家可以去开篇给出的链接下载动画效果源码,实现各种炫酷的动画!

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


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








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值