Android框架之路——RecyclerView的使用
来源:互联网 发布:山治 知乎 编辑:程序博客网 时间:2024/06/08 09:28
参考博客:
- Android RecyclerView 使用完全解析 体验艺术般的控件
- 这是一篇Android RecyclerView使用介绍哦
Demo下载
下载链接
遇到的问题
- android stuido关于在V7包下找不到recyclerview的解决办法
RecyclerView简介
RecyclerView是Android 5.0提供的新控件,该控件用于在有限的窗口中展示大量数据集。RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。
RecyclerView比Listview更先进更灵活,对于很多的视图它就是一个容器,可以有效的重用和滚动。当数据动态变化的时候请使用它。
RecyclerView使用结构
- RecyclerView.Adapter : 创建View并将数据集合绑定到View上
- ViewHolder : 持有所有的用于绑定数据或者需要操作的View
- LayoutManager : 布局管理器,负责摆放视图等相关操作
- ItemDecoration : 负责绘制Item附近的分割线,通过RecyclerView.addItemDecoration()使用
- ItemAnimator : 为Item的操作添加动画效果,如,增删条目等,通过RecyclerView.setItemAnimator(new DefaultItemAnimator())使用
前俩条使用过Listview优化的一定不会陌生,后三条则用来自定义布局,分界线和动画效果。
使用流程
>1、基础使用
- 创建project,导入v7包;
修改activity_main.xml,添加RecycleView布局;
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.ping.recyclerview.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
新增item.xml,包含一个TextView;
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#abcdef" android:layout_height="wrap_content" > <TextView android:id="@+id/id_num" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="1" /></FrameLayout>
新建一个MyRecyclerViewAdapter.java,继承自RecyclerView.Adapter,同时泛型中添加上一个ViewHolder,实现三个方法,如下:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{ @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return null; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { } @Override public int getItemCount() { return 0; } public class MyViewHolder extends RecyclerView.ViewHolder { public MyViewHolder(View itemView) { super(itemView); } }}
实现MyRecyclerViewAdapter中的方法;
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{ private List<String> data; private Context mContext; public MyRecyclerViewAdapter(List<String> data, Context context) { super(); this.data = data; this.mContext = context; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false); MyViewHolder holder = new MyViewHolder(view); return holder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.mTextView.setText(""+data.get(position)); } @Override public int getItemCount() { return data.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { TextView mTextView; public MyViewHolder(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(R.id.id_num); } }}
实现MainActivity.java;
public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private List<String> mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setAdapter(new MyRecyclerViewAdapter(mDatas, this)); } protected void initData() { mDatas = new ArrayList<>(); for (int i = 'A'; i < 'z'; i++) { mDatas.add("" + (char) i); } }}
- 实现效果;
>2、进阶使用
设置点击事件
Adapter中添加接口,这种方法的思想是通过setter方法给Adapter注入OnRecyclerViewItemClickListener接口实例,注入实例时要对应实现接口中的监听长短按的方法。注入实例后的Adapter可以使用实例的俩个方法,对Adapter来说此时就美滋滋…直接可以调用了。这里给出的只是一种写法,网上还有其他写法,思想类似,可参照。
......private OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener;public MyRecyclerViewAdapter(List<String> data, Context context) { super(); this.data = data; this.mContext = context;}public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener) { mOnRecyclerViewItemClickListener = onRecyclerViewItemClickListener;}public interface OnRecyclerViewItemClickListener { void onItemClick(View view, int position); void onItemLongClick(View view, int position);}.......@Overridepublic void onBindViewHolder(MyViewHolder holder, final int position) { holder.mTextView.setText(""+data.get(position)); if(mOnRecyclerViewItemClickListener!=null){ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOnRecyclerViewItemClickListener.onItemClick(v, position); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { mOnRecyclerViewItemClickListener.onItemLongClick(v, position); return true; } }); }}......
MainActivity中实现接口中的方法
....mAdapter = new MyRecyclerViewAdapter(mDatas, this);mAdapter.setOnRecyclerViewItemClickListener(new MyRecyclerViewAdapter.OnRecyclerViewItemClickListener() { @Override public void onItemClick(View view, int position) { Log.i("MainActivity", "short"); } @Override public void onItemLongClick(View view, int position) { Log.i("MainActivity", "long"); }});mRecyclerView.setAdapter(mAdapter);.....
设置分割线
参考博客有对应的实现方案,这里就照搬一下了;
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) { Log.v("itemdecoration", "onDraw()"); 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); android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext()); 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); } }}
在MainActivity.java中增加一行,为RecyclerView设置分割线;
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
- 实现效果:
自定义分割线
1、在styles.xml中重定义系统的listDivider,如下:
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:listDivider">@drawable/divider_bg</item> </style> </resources>
2、在drawable下创建divider_bg.xml;
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:centerColor="#abc" android:endColor="#fff" android:startColor="#000" android:type="linear" /> <size android:height="4dp"/> </shape>
3、实现效果,有点丑,但是功能到位就好。(宽度可以通过上面的height设置)
设置布局
我们通过mRecyclerView.setLayoutManager(new LinearLayoutManager(this))来设置了布局为线性布局,系统共提供了三个布局,分别是:
- LinearLayoutManager 线性管理器,支持横向、纵向;
- GridLayoutManager 网格布局管理器;
- StaggeredGridLayoutManager 瀑布流式布局管理器
下面我们来进行另外俩种布局管理器的学习演示。
GridLayoutManager
1、更改设置布局的代码,第二个参数为几列;
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
2、给Item设置margin,中间留白;
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#abcdef" android:layout_marginLeft="1dp" android:layout_marginRight="1dp" android:layout_marginTop="1dp" android:layout_marginBottom="1dp" android:layout_height="wrap_content" > <TextView android:id="@+id/id_num" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="1" /></FrameLayout>
3、效果如下;
StaggeredGridLayoutManager
1、使用StaggeredGridLayoutManager同样可以实现上面GridLayoutManager的效果。
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
2、效果如下;
使用StaggeredGridLayoutManager实现瀑布流的效果,修改Adapter如下:
....private List<Integer> mHeights;....public MyRecyclerViewAdapter(List<String> data, Context context) { super(); this.data = data; this.mContext = context; mHeights = new ArrayList<Integer>(); for (int i = 0; i < data.size(); i++) { mHeights.add( (int) (150 + Math.random() * 200)); }}....@Overridepublic void onBindViewHolder(MyViewHolder holder, final int position) { holder.mTextView.setText(""+data.get(position)); ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); layoutParams.height = mHeights.get(position); if(mOnRecyclerViewItemClickListener!=null){ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOnRecyclerViewItemClickListener.onItemClick(v, position); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { mOnRecyclerViewItemClickListener.onItemLongClick(v, position); return true; } }); }}
效果如下:
个人公众号:每日推荐一篇技术博客,坚持每日进步一丢丢…欢迎关注,想建个微信群,主要讨论安卓和Java语言,一起打基础、用框架、学设计模式,菜鸡变菜鸟,菜鸟再起飞,愿意一起努力的话可以公众号留言,谢谢…
- Android框架之路——RecyclerView的使用
- Android框架之路——Glide加载图片(结合RecyclerView、CardView)
- Android框架之路——Banner实现轮播图(RecyclerView添加Header)
- Android框架之路——Glide加载图片(结合RecyclerView、CardView)
- Android框架之路——Banner实现轮播图(RecyclerView添加Header)
- Android之RecyclerView使用
- Android学习之路------RecyclerView的使用(1)
- Android RecyclerView 的基本使用之GridView
- Android控件之RecyclerView的基本使用
- Android开发之RecyclerView的使用
- Android之RecyclerView的使用总结
- 【Android - MD】之RecyclerView的使用
- Android组件之RecyclerView的基本使用
- Android 开发之RecyclerView的使用
- android学习之RecyclerView的简单使用
- Android框架之路——ToolBar的使用
- Android框架之路——Glide的使用
- Android框架之路——ButterKnife的使用
- REST Service 开发
- VS2015安装带来的一堆事
- 电码加密(字符数组和指针的应用)
- python学习之代码规范
- JS作用域、作用域链与闭包详解
- Android框架之路——RecyclerView的使用
- NYOJ12 喷水装置(二)
- 学习淘淘商城第二十三课(添加商品的实现)
- 数据结构---递归用法
- [Android]通过JNI实现卸载自身App后台发送Http请求~
- 第一章
- VS2013或15 MVC提示“当前上下文中不存在ViewBag”的解决方案
- es6箭头函数
- Hadoop安装配置详解