Android控件RecyclerView的基本用法
2017-05-17 20:20
375 查看
RecyclerView是Android提供的一个功能强大的滚动控件,是增强版的ListView和GridView,不仅可以轻松实现和ListView相同的效果,还优化了ListView中存在的各种不足之处;目前Android官方更加推荐使用RecyclerView,本文介绍一下Android Studio中RecyclerView的基本用法。
RecyclerView需要通过setLayoutManager()方法设置布局管理器,RecyclerView有三个默认布局管理器LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager,它们都支持横向和纵向排列以及反向滑动。如果想把RecyclerView改为横向滑动,可以通过调用:
RecyclerView是Android新增的控件,为了让RecyclerView在所有的Android版本上都可以使用,Android团队采取了将RecyclerView定义在support库中,所以,我们如果要使用RecyclerView这个控件,首先需要在项目中的build.gradle(Module:app)中添加相应的依赖库;
打开build.gradle(Module:app)文件,在dependencies闭包中添加如下内容:
添加过之后点击Sync Now进行同步,同步完后,接下来修改主布局activity_main.xml,如下:
在布局中加入RecyclerView控件,需要注意的是,由于RecyclerView并不是内置在系统SDK中的,所以需要把完整的包路径写出来;
为RecyclerView新建一个适配器类FruitAdapter,并让其继承自RecyclerView.Adapter,并指定其泛型为FruitAdapter.MyViewHolder,MyViewHolder是FruitAdapter的内部类;如下:
fruit_item.xml的代码如下:
Fruit.java的代码如下:
修改MainActivity中的代码,如下:
运行,效果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/07/b3e1ecd23ffd00c644330240dc666e5f)
1、修改代码,使的RecyclerView实现水平滚动效果,把fruit_item.xml中的元素改成垂直排列,修改布局的相关属性等,如下:
2、修改MainActivity的代码实现水平滚动,加入:
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 改变RecyclerView的方向
效果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/07/66457ef7e2e9211e413fc36b3a09e35c)
3、修改MainActivity的代码实现网格布局,如下:
GridLayoutManager layoutManager = new GridLayoutManager(this, 3); // 第二个参数表示每行显示的个数
效果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/07/bf620eb2063cf5dce19e2f5fad81f0fd)
4、再次修改MainActivity的代码和fruit_item的代码,实现瀑布流布局,上面的MainActivity代码就是修改后的,瀑布流布局需要各个子项高度不一致才能看出来,图片大小都一样,为此只有在TextView中多加一些字啦!效果如下所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/07/7c99bbbc9e54b6ea84ce0da6569a944b)
RecyclerView不同于ListView的点击事件,RecyclerView不像ListView一样提供item的点击监听,所以需要我们自己实现给子项具体的View去注册点击事件。RecyclerView的item点击事件监听可以向我代码中为item的view设置监听,也可以在recyclerView.addOnItemTouchListener里去判断手势来实现。
另外,代码后续实现了通过点击按钮动态的添加和删除RecyclerView中的Item子项,通过添加和删除可以更好的理解RecyclerView的三种布局管理器;
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/07/15ab8f5969766c576b79215e2f3a378a)
ItemTouchHelper是一个处理RecyclerView的滑动删除和拖拽的辅助类,RecyclerView 的item拖拽移动和滑动删除就靠它来实现。ItemTouchHelper需要在RecyclerView初始化的时候调用
通过attachToRecyclerView与RecyclerView 绑定后生效,如果想要为Item设置拖拽和滑动时的响应动画效果,可以重写ItemTouchHelper的三个方法来实现:onSelectedChanged、clearView、onChildDraw,具体的实现见代码;
文中代码地址:MyRecyclerView
RecyclerView需要通过setLayoutManager()方法设置布局管理器,RecyclerView有三个默认布局管理器LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager,它们都支持横向和纵向排列以及反向滑动。如果想把RecyclerView改为横向滑动,可以通过调用:
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 改变RecyclerView的方向
RecyclerView是Android新增的控件,为了让RecyclerView在所有的Android版本上都可以使用,Android团队采取了将RecyclerView定义在support库中,所以,我们如果要使用RecyclerView这个控件,首先需要在项目中的build.gradle(Module:app)中添加相应的依赖库;
打开build.gradle(Module:app)文件,在dependencies闭包中添加如下内容:
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "neu.cn.myrecyclerview" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:recyclerview-v7:25.3.1' testCompile 'junit:junit:4.12' }
添加过之后点击Sync Now进行同步,同步完后,接下来修改主布局activity_main.xml,如下:
<?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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="neu.cn.myrecyclerview.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/add_item" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Add Item" android:textAllCaps="false" /> <Button android:id="@+id/delete_item" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Delete Item" android:textAllCaps="false" /> </LinearLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
在布局中加入RecyclerView控件,需要注意的是,由于RecyclerView并不是内置在系统SDK中的,所以需要把完整的包路径写出来;
为RecyclerView新建一个适配器类FruitAdapter,并让其继承自RecyclerView.Adapter,并指定其泛型为FruitAdapter.MyViewHolder,MyViewHolder是FruitAdapter的内部类;如下:
package neu.cn.myrecyclerview; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.util.List; import java.util.Random; /** * Created by neuHenry on 2017/6/1. */ public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.MyViewHolder> { private List<Fruit> mFruitList; public FruitAdapter(List<Fruit> mFruitList) { this.mFruitList = mFruitList; } @Override public MyViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false); final MyViewHolder holder = new MyViewHolder(view); holder.fruitView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); Fruit fruit = mFruitList.get(position); Toast.makeText(v.getContext(), "you clicked fruitView " + fruit.getImageName(), Toast.LENGTH_SHORT).show(); } }); holder.fruitImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); Fruit fruit = mFruitList.get(position); Toast.makeText(v.getContext(), "you clicked fruitImage " + fruit.getImageName(), Toast.LENGTH_SHORT).show(); } }); holder.fruitName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); Fruit fruit = mFruitList.get(position); Toast.makeText(v.getContext(), "you clicked fruitName " + fruit.getImageName(), Toast.LENGTH_SHORT).show(); } }); return holder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageID()); holder.fruitName.setText(fruit.getImageName()); } @Override public int getItemCount() { return mFruitList.size(); } /** * RecyclerView 中动态添加Item * @param position */ public void addItem(int position) { Random random = new Random(mFruitList.size()); int index = random.nextInt(mFruitList.size()); Fruit fruit = mFruitList.get(index); mFruitList.add(fruit); notifyItemInserted(position); } /** * RecyclerView 中动态删除Item * @param position */ public void deleteItem(int position) { mFruitList.remove(position); notifyItemRemoved(position); } class MyViewHolder extends RecyclerView.ViewHolder { View fruitView; ImageView fruitImage; TextView fruitName; public MyViewHolder(View view) { super(view); fruitView = view; fruitImage = (ImageView) view.findViewById(R.id.fruit_image); fruitName = (TextView) view.findViewById(R.id.fruit_name); } } }
fruit_item.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:orientation="horizontal"> <ImageView android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" /> </LinearLayout>
Fruit.java的代码如下:
package neu.cn.myrecyclerview; /** * Created by neuHenry on 2017/6/1. */ public class Fruit { private int imageID; private String imageName; public Fruit(int imageID, String imageName) { this.imageID = imageID; this.imageName = imageName; } public int getImageID() { return imageID; } public String getImageName() { return imageName; } }
修改MainActivity中的代码,如下:
package neu.cn.myrecyclerview; import android.content.Context; import android.graphics.Canvas; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.DisplayMetrics; import android.view.View; import android.view.WindowManager; import android.widget.Button; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 水果数据列表,存放水果数据 private List<Fruit> fruitList = new ArrayList<>(); private RecyclerView recyclerView; private FruitAdapter fruitAdapter; // 处理RecyclerView中Item的滑动和拖拽 private ItemTouchHelper itemTouchHelper; private WindowManager windowManager; private Button addItem; private Button deleteItem; private int screenwidth; private Boolean remove; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits(); fruitAdapter = new FruitAdapter(fruitList); remove = false; addItem = (Button) findViewById(R.id.add_item); deleteItem = (Button) findViewById(R.id.delete_item); windowManager = (WindowManager) MainActivity.this.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(outMetrics); screenwidth = outMetrics.widthPixels; // 获取屏幕宽度 addItem.setOnClickListener(this); deleteItem.setOnClickListener(this); itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() { // 用于设置拖拽和滑动的方向 @Override public int getMovementFlags(RecyclerView recyclerV f01a iew, RecyclerView.ViewHolder viewHolder) { int dragFlags = 0, swipeFlags = 0; if (recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager || recyclerView.getLayoutManager() instanceof GridLayoutManager) { // 瀑布流和网格布局有四个拖拽方向 dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; } else if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { // 线性布局有两个拖拽方向 dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; // 设置侧滑方向为从两个方向都可以 swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; } return makeMovementFlags(dragFlags, swipeFlags); } // 长摁Item拖拽时会回调这个方法 @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { int from = viewHolder.getAdapterPosition(); int to = target.getAdapterPosition(); Collections.swap(fruitList, from, to); // 交换fruitList中数据的位置 fruitAdapter.notifyItemMoved(from, to); // 更新适配器中item的位置 return true; } // 处理滑动删除操作 @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { fruitAdapter.deleteItem(viewHolder.getAdapterPosition()); fruitAdapter.notifyDataSetChanged(); } @Override public boolean isLongPressDragEnabled() { return true; // 返回true则为所有Item都设置可以拖拽 } // 当Item拖拽开始时调用 @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { viewHolder.itemView.setElevation(100); } } } // 当Item拖拽完成时调用 @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { viewHolder.itemView.setElevation(0); } } // 当Item视图变化时调用 @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { viewHolder.itemView.scrollTo(-(int) dX, -(int) dY); // 根据Item的滑动偏移修改HorizontalScrollView的滚动 if (Math.abs(dX) > screenwidth / 5 && !remove && isCurrentlyActive) { // 用户收滑动Item超过屏幕5分之1,标记为要删除 remove = true; } else if (Math.abs(dX) < screenwidth / 5 && remove && !isCurrentlyActive) { // 用户收滑动Item没有超过屏幕5分之1,标记为不删除 remove = false; } if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && remove == true && !isCurrentlyActive) { // 当用户滑动Item超过屏幕5分之1,并且松手时,执行删除Item if (viewHolder != null && viewHolder.getAdapterPosition() >= 0) { fruitAdapter.deleteItem(viewHolder.getAdapterPosition()); remove = false; } } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }); recyclerView = (RecyclerView) findViewById(R.id.recycler_view); // 与RecyclView绑定 itemTouchHelper.attachToRecyclerView(recyclerView); // 线性布局 LinearLayoutManager layoutManager = new LinearLayoutManager(this); // layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 改变RecyclerView的方向 // 网格布局 // GridLayoutManager layoutManager = new GridLayoutManager(this, 3); // 第二个参数表示每行显示的个数 // 瀑布流布局 // StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(fruitAdapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); // 设置Item加载或移除时的动画 } /** * 初始化水果数据列表 */ private void initFruits() { for (int i = 0; i < 2; i++) { Fruit apple = new Fruit(R.drawable.apple_pic, getRandomName("Apple")); fruitList.add(apple); Fruit banana = new Fruit(R.drawable.banana_pic, getRandomName("Banana")); fruitList.add(banana); Fruit orange = new Fruit(R.drawable.orange_pic, getRandomName("Orange")); fruitList.add(orange); Fruit watermelon = new Fruit(R.drawable.watermelon_pic, getRandomName("Watermelon")); fruitList.add(watermelon); Fruit pear = new Fruit(R.drawable.pear_pic, getRandomName("Pear")); fruitList.add(pear); Fruit grape = new Fruit(R.drawable.grape_pic, getRandomName("Grape")); fruitList.add(grape); Fruit pineapple = new Fruit(R.drawable.pineapple_pic, getRandomName("Pineapple")); fruitList.add(pineapple); Fruit strawberry = new Fruit(R.drawable.strawberry_pic, getRandomName("Strawberry")); fruitList.add(strawberry); Fruit cherry = new Fruit(R.drawable.cherry_pic, getRandomName("Cherry")); fruitList.add(cherry); Fruit mango = new Fruit(R.drawable.mango_pic, getRandomName("Mango")); fruitList.add(mango); } } private String getRandomName(String name) { StringBuffer buffer = new StringBuffer(); Random random = new Random(20); int length = random.nextInt(20); for (int i = 0; i < length; i++) { buffer.append(name); } return buffer.toString(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.add_item: // RecyclerView中添加Item fruitAdapter.addItem(fruitList.size()); break; case R.id.delete_item: // // RecyclerView中删除Item fruitAdapter.deleteItem(fruitList.size() - 1); break; default: break; } } }
运行,效果如下:
1、修改代码,使的RecyclerView实现水平滚动效果,把fruit_item.xml中的元素改成垂直排列,修改布局的相关属性等,如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="100dp" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"/> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="10dp" /> </LinearLayout>
2、修改MainActivity的代码实现水平滚动,加入:
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 改变RecyclerView的方向
效果如下:
3、修改MainActivity的代码实现网格布局,如下:
GridLayoutManager layoutManager = new GridLayoutManager(this, 3); // 第二个参数表示每行显示的个数
效果如下:
4、再次修改MainActivity的代码和fruit_item的代码,实现瀑布流布局,上面的MainActivity代码就是修改后的,瀑布流布局需要各个子项高度不一致才能看出来,图片大小都一样,为此只有在TextView中多加一些字啦!效果如下所示:
RecyclerView不同于ListView的点击事件,RecyclerView不像ListView一样提供item的点击监听,所以需要我们自己实现给子项具体的View去注册点击事件。RecyclerView的item点击事件监听可以向我代码中为item的view设置监听,也可以在recyclerView.addOnItemTouchListener里去判断手势来实现。
另外,代码后续实现了通过点击按钮动态的添加和删除RecyclerView中的Item子项,通过添加和删除可以更好的理解RecyclerView的三种布局管理器;
ItemTouchHelper是一个处理RecyclerView的滑动删除和拖拽的辅助类,RecyclerView 的item拖拽移动和滑动删除就靠它来实现。ItemTouchHelper需要在RecyclerView初始化的时候调用
itemTouchHelper.attachToRecyclerView(recyclerView);
通过attachToRecyclerView与RecyclerView 绑定后生效,如果想要为Item设置拖拽和滑动时的响应动画效果,可以重写ItemTouchHelper的三个方法来实现:onSelectedChanged、clearView、onChildDraw,具体的实现见代码;
文中代码地址:MyRecyclerView
相关文章推荐
- android 5.0新特性,recyclerview的基本用法,及应注意的问题
- Android App开发中RecyclerView控件的基本使用教程
- Android中RecyclerView的基本用法
- Android AutoCompleteTextView控件基本用法示例
- android RecyclerView的基本介绍及用法(一)
- Android控件之RecyclerView的基本使用
- Android RecyclerView的基本用法
- Android MaterialDesign控件使用以及RecyclerView,ItemDecoration的基本使用
- 强大的滚动控件——RecyclerView(一)基本用法
- RecyclerView的基本用法 (一个控件实现ListView, GridView等效果)+接口回调点击事件
- Android的ListView和RecyclerView的基本用法
- Android RecyclerView 基本用法&进阶
- 一步一步学android之基本控件——TextView组件
- android中view控件的setTag()和getTag()用法和功能介绍
- android基础控件EditView用法介绍
- Android中的常用控件及其基本用法
- ImageView显示图像控件(基本用法)
- Android搜索控件SearchView的用法
- android之AutoCompleteTextView控件用法
- Android ListView控件基本用法以及范例