RecyclerView
来源:互联网 发布:黑色星期五海淘 知乎 编辑:程序博客网 时间:2024/06/07 02:08
先给大家看一下效果:
个人关于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);//设置adaptermRecyclerView.setAdapter(mRecyclerViewAdapter);//设置listview垂直如何显示mLinearLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);//创建默认的线性布局LinearlayoutmRecyclerView.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"/>
编写分割线样式
最后操作style.xml:
分割线就添加完成了,效果如下:
效果还挺不错的吧。一般我们可能不会用到,因为在item中直接添加View比这种方式简单多了,嘻嘻。
完成这些之后,实现其他几种效果就是设置不同的LayoutManager样式了,代码如下:
//ListViewcase R.id.action_listview: mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); break;//GridViewcase R.id.action_gridview: mRecyclerView.setLayoutManager(new GridLayoutManager(this,3)); break;//水平GridVIewcase 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@Overridepublic 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
转载自:http://blog.csdn.net/csdnfml/article/details/49999023
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- RecyclerView
- 通过距离感应器获取实际距离[FAQ04538][Sensor]java层获得P_sensor距离传感器当前真实值,不止0,1
- JVM内存区域模型
- 根据两点经纬度计算距离
- 一些算法题
- GMM:高斯混合模型的数学推导笔记(上)
- RecyclerView
- activiti流程图动态创建
- 剑指Offer--028-字符串的排列
- spark sql简单示例
- KindEditor得不到textarea值的解决方法
- 个人常用iOS第三方库
- android BitmapFactroy
- 介绍 GDB 调试 Go
- GetKeyState、GetAsyncKeyState、GetKeyboardState函数的区别 以及虚拟键值