10读书笔记之更强大的滚动控件-----RecyclerView
来源:互联网 发布:cf手游一键领取软件 编辑:程序博客网 时间:2024/05/21 21:29
更强大的滚动控件—–RecyclerView
ListView由于强大的功能,在过去的Android开发当中可以说是贡献卓越,直到今天仍然还有不计其数的程序再继续使用着ListView。不过ListView并不是完全没有缺点的,比如说如果我们不使用一些技巧来提升它的运行效率,那么ListView的性能就会非常差,还有,ListView的扩展性也不够好,它只能实现数据纵向滚动的效果,如果我们想实现横向滚动的话,ListView是做不到的。
为此,Android提供了一个更强大的滚动控件——RecyclerView。他可以说是一个增强版的ListView,不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的各种不足之处。
目前Android官方更加推荐使用RecyclerView,未来也会有更多的程序逐渐从ListView转向RecyclerView。
首先新建一个RecyclerViewTest项目,并让Android Studio自动帮我们创建好活动。
RecyclerView的基本用法。
和百分比布局类似,RecyclerView也属于新增的控件,为了让RecyclerView在所有的Android版本上都能使用,Android团队采取了同样的方式,将RecyclerView定义在了support库当中。因此,想要使用RecyclerView这个控件,首先需要在项目的build.gradle中添加相应的依赖库才行。
打开app/build.gradle文件,在dependencies闭包中添加如下内容:
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'compile 'com.android.support.constraint:constraint-layout:1.0.2'testCompile 'junit:junit:4.12'}
添加完之后记得要点击一下Sync Now来进行同步。然后修改antivity_main.xml中的代码。如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
在布局中加入RecyclerView控件也是非常简单的,先为RecyclerView指定一个id,然后将宽度和高度都设置为match_parent,这样RecyclerView也就占满了整个布局的控件。需要注意的是:由于RecyclerView并不是内置在系统SDK当中的,所以需要把完整的包路径写出来。
这里想要使用RecyclerView来实现和ListView相同的效果,因此就需要准备一份同样的水果图片。简单起见,我们就直接从ListViewTest项目中把图片复制过来就可以了,另外顺便将Fruit类和fruit_item.xml也复制过来,省的将同样的代码再写一遍。
接下来需要为RecyclerView准备一个适配器,新建FruitAdapter类,让这个适配器继承自RecyclerView.Adapter中定义的一个内部类,代码如下所示:
package net.nyist.lenovo.recyclerviewtest;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 java.util.List;public class FruitAdapter extends RecyclerView.Adapter <FruitAdapter.ViewHolder>{private List<Fruit> mFruitList;static class ViewHolder extends RecyclerView.ViewHolder{ ImageView fruitImage; TextView fruitName; public ViewHolder(View view){ super(view); fruitImage = (ImageView)view.findViewById(R.id.fruit_image); fruitName = (TextView)view.findViewById(R.id.fruit_name); }}public FruitAdapter(List<Fruit> fruitList){ mFruitList = fruitList;}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false); ViewHolder holder = new ViewHolder(view); return holder;}@Overridepublic void onBindViewHolder(ViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName());}@Overridepublic int getItemCount() { return mFruitList.size();}}
虽然这段代码看上去好像有点长,但是其实它比ListView的适配器更容易理解。这里我们首先定义了一个内部类ViewHolder,ViewHolder要继承自RecyclerView.ViewHolder。然后ViewHolder的构造函数中要传入一个View参数,这个参数通常就是RecyclerView子项的最外层布局,那么我们就可以通过findViewById()方法来获取到布局中的ImageView和TextView的实例了。
接着往下看,FruitAdapter中也有一个构造函数,这个方法用于把要展示的数据源传进来,并赋值给一个全局变量mFruitList我们的后续操作都是在这个数据源的基础上进行的。
继续往下看,由于FruitAdapter是继承自RecyclerView.Adapter的,那么就必须重写onCreateViewHolder(),onBindViewHolder()和getItemCount()这三个方法。onCreateViewHolder()方法是用于创建一个ViewHolder实例的,我们在这个方法中将fruit_item布局加载进来,然后创建一个ViewHolder实例,并把加载出来的布局传入到构造函数当中,最后将ViewHolder的实例返回。onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值,的,会在每个子项被滚动到屏幕内的时候执行,这里我们通过position参数得到当前的Fruit实例,然后再将数据设置到ViewHolder的ImageView和TextView当中即可。getItemCount()方法就非常简单了,它用于告诉RecyclerView一共有多少子项,直接返回数据源的在长度就可以了。
适配器准备好了之后,我们就可以开始使用RecyclerView了,修改MainActivity中的代码,如下所示:
package net.nyist.lenovo.recyclerviewtest;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.LinearLayoutCompat;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {private List<Fruit> fruitList = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();//初始化水果数据。 RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); FruitAdapter adapter = new FruitAdapter(fruitList); recyclerView.setAdapter(adapter);}private void initFruits(){ for (int i = 0;i < 2;i++){ Fruit apple = new Fruit("Apple",R.drawable.apple_pic); fruitList.add(apple); Fruit banana = new Fruit("Banana",R.drawable.banana_pic); fruitList.add(banana); Fruit orange = new Fruit("Orange",R.drawable.orange_pic); fruitList.add(orange); Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon_pic); fruitList.add(watermelon); Fruit pear = new Fruit("Pear",R.drawable.pear_pic); fruitList.add(pear); Fruit grape = new Fruit("Grape",R.drawable.grape_pic); fruitList.add(grape); Fruit pineapple = new Fruit("Pineapple",R.drawable.pineapple_pic); fruitList.add(pineapple); Fruit strawberry = new Fruit("Strawberry",R.drawable.strawberry_pic); fruitList.add(strawberry); Fruit cherry = new Fruit("Cherry",R.drawable.cherry_pic); fruitList.add(cherry); Fruit mango = new Fruit("Mango",R.drawable.mango_pic); fruitList.add(mango); }}}
图片暂时没有。不过已经运行出来。
实现横向滚动和瀑布流布局
我们已经知道,ListView的扩展性并不好,他只能实现纵向滚动的效果,如果想进行横向滚动的话,ListView就做不到了。那么RecyclerView就能做了。不仅可以做到,还非常简单。
首先要对fruit_item布局进行修改,因为目前这个布局里面的元素是水平排列的,适用于纵向滚动的场景,而如果我们要实现横向滚动的话,应该把fruit_item里的元素改成垂直排列才比较合适。修改fruit_item.xml中的代码,如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="100dp"android:layout_height="wrap_content"><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>
可以看到,我们将LinearLayout改成垂直方向排列,并把宽度设为100dp。这里将宽度指定为固定值是因为每种水果的文字长度不一致,如果使用wrap_content的话,RecyclerView的子项就会有长短,非常不美观,而如果用match_parent的话,就会导致宽度过长,一个子项占满整个屏幕。
然后我们将ImageView和TextView都设置成了在布局中水平居中,并且使用layout_marginTop属性让文字和图片之间保持一些距离。
接下来修改MainActivity中的代码,如下所示:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();//初始化水果数据。 RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(layoutManager); FruitAdapter adapter = new FruitAdapter(fruitList); recyclerView.setAdapter(adapter);}······
MainActivity中只加入了一行代码,调用LinearLayoutManager的setOrientation()方法来设置布局的排列方向,默认是纵向排列,我们传入LinearLayoutManager.HORIZONTAL表示让布局横向排列,这样RecyclerView就可以横向滚动了。
除了LinearLayoutManager之外,RecyclerView还给我们提供了GridLayoutManger和StaggeredGridLayoutManager可以用于实现瀑布流布局。现在开始实现一下。
首先还是修改一下fruit_item.xml中的代码,如下所示:
package net.nyist.lenovo.recyclerviewtest;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.LinearLayoutCompat;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import java.util.ArrayList;import java.util.List;import java.util.Random;public class MainActivity extends AppCompatActivity {private List<Fruit> fruitList = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();//初始化水果数据。 RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); FruitAdapter adapter = new FruitAdapter(fruitList); recyclerView.setAdapter(adapter);}private void initFruits(){ for (int i = 0;i < 2;i++){ Fruit apple = new Fruit(getRandomLengthName("Apple"),R.drawable.apple_pic); fruitList.add(apple); Fruit banana = new Fruit(getRandomLengthName("banana"),R.drawable.banana_pic); fruitList.add(banana); Fruit orange = new Fruit(getRandomLengthName("orange"),R.drawable.orange_pic); fruitList.add(orange); Fruit watermelon = new Fruit(getRandomLengthName("watermelon"),R.drawable.watermelon_pic); fruitList.add(watermelon); Fruit pear = new Fruit(getRandomLengthName("Pear"),R.drawable.pear_pic); fruitList.add(pear); Fruit grape = new Fruit(getRandomLengthName("Grape"),R.drawable.grape_pic); fruitList.add(grape); Fruit pineapple = new Fruit(getRandomLengthName("Pineapple"),R.drawable.pineapple_pic); fruitList.add(pineapple); Fruit strawberry = new Fruit(getRandomLengthName("Strawberry"),R.drawable.strawberry_pic); fruitList.add(strawberry); Fruit cherry = new Fruit(getRandomLengthName("Cherry"),R.drawable.cherry_pic); fruitList.add(cherry); Fruit mango = new Fruit(getRandomLengthName("Mango"),R.drawable.mango_pic); fruitList.add(mango); }}private String getRandomLengthName(String name){ Random random = new Random(); int length = random.nextInt(20)+1; StringBuilder builder = new StringBuilder(); for (int i = 0;i < length;i++){ builder.append(name); } return builder.toString();}}
RecyclerView的点击事件
和ListView一样,RecyclerView也必须要能影响点击事件才可以,不然的话就没有什么实际用途了,不过不同于ListView的是,RecyclerView并没有提供类似于setOnItemClickListener()这样的注册监听器方法,而是需要我们自己给子项具体的View去注册点击事件,相比于ListView来说,实现起来要复杂一些。
ListView在点击事件上的处理并不人性化,setOnItemClickListener()方法注册的子项的点击事件,但如果我想点击的是子项里具体的某一个按钮呢?虽然ListView也是能做到的,但是实现起来就相对比较麻烦了。为此,RecycylerView干脆直接摒弃了子项点击事件的监听器,所有的点击事件都由具体的View去注册,就再没有这个困扰了。
下面开始如何在RecyclerView中注册点击事件,修改FruitAdapter中的代码:如下所示:
package net.nyist.lenovo.recyclerviewtest;
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;public class FruitAdapter extends RecyclerView.Adapter <FruitAdapter.ViewHolder>{private List<Fruit> mFruitList;static class ViewHolder extends RecyclerView.ViewHolder{ View fruitView; ImageView fruitImage; TextView fruitName; public ViewHolder(View view){ super(view); fruitView = view; fruitImage = (ImageView)view.findViewById(R.id.fruit_image); fruitName = (TextView)view.findViewById(R.id.fruit_name); }}public FruitAdapter(List<Fruit> fruitList){ mFruitList = fruitList;}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false); final ViewHolder holder = new ViewHolder(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 view"+fruit.getName(),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 image"+fruit.getName(),Toast.LENGTH_SHORT).show(); } }); return holder;}@Overridepublic void onBindViewHolder(ViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName());}@Overridepublic int getItemCount() { return mFruitList.size();}}
- 10读书笔记之更强大的滚动控件-----RecyclerView
- RecyclerView -- 更强大的滚动控件1
- RecyclerView--更强大的滚动控件2
- Material Design学习之RecyclerView(更强大的滚动控件)(4)
- 强大的滚动控件RecyclerView
- Android 强大的滚动控件 RecyclerView
- 识更加强大的滚动控件——RecyclerView
- 强大的滚动控件——RecyclerView(二)横向滚动
- 强大的滚动控件——RecyclerView(一)基本用法
- 强大的滚动控件——RecyclerView(三)瀑布流效果
- 强大的Android控件之RecyclerView体验艺术般的控件
- Android开发之滚动控件RecyclerView
- Android强大的滚动控件--RecylerView
- (更新版)Android VideoPlayer 在滚动列表实现item视频播放(ListView控件和RecyclerView)
- 使用RecyclerView实现滚动控件
- 居中滚动的Recyclerview
- 强大的是更强大的战斗力
- RecyclerView更全解析之
- ROM 之 DDS的调相
- msql的left join、right join、inner join的区别
- HDU 4548 有感而发 对素数打表进行优化
- Spring Boot 系列(七)Swagger2-生成RESTful接口文档
- NDK示例:native-activity
- 10读书笔记之更强大的滚动控件-----RecyclerView
- Singleton
- 多线程之Callable接口及FutureTask源码分析
- Java集合框架之_Collection接口
- Spring整合Hibernate
- JavaScript-DOM(上篇)
- 关于浮动的影响及处理方案
- JavaScript笔记(AJAX 与 JSONP)
- Redis源码阅读笔记—sds