我们知道,ListView只能实现数据纵向滚动的效果,RecyclerView可以说是增强版的List View,不仅可以轻松实现和ListView同样的效果,还优化了ListView的不足之处,目前官方是更加推荐RecyclerView,首先来新建一个RecyclerViewTest项目
一、纵向滚动
首先我们需要在app/build.gradle文件中添加依赖,
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:recyclerview-v7:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }
添加完记得Sync Now,接着修改activity_main.xml,
在布局中加入RecyclerView控件是非常简单的,先为RecyclerView指定一个id,然后设置高度和宽度为match_parent,这样会占满整个布局的空间,要注意的是由于RecyclerView并不是内置在系统SDK中的,需要把完整的路径写出来
这里我做的是一个水果的展示,然后建立Fruit.java
package com.example.recyclerviewtest; public class Fruit { private String name; private int imageId; public Fruit(String name, int imageId){ this.name = name; this.imageId = imageId; } public String getName(){ return name; } public int getImageId(){ return imageId; } }
接着建立fruit_item.xml
接下来我们需要为RecycleView准备一个适配器,新建FruitAdapter.java,让这个适配器继承RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder,然后在ViewHolder的构造参数中要传入一个View参数,这个参数通常就是RecyclerView子项的最外层布局,通过findViewById()方法来获取布局中的ImageView和TextView
package com.example.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 { private List 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); } } // 传入一个构造函数,把数据源传进来,并赋值给全局变量mFruitList public FruitAdapter(List fruitList){ mFruitList = fruitList; } /** *由于FruitAdapter是继承于RecyclerView.Adapter,那么必须重写onCreateViewHolder()、 *onBindViewHolder()、getItemCount()这3个方法,onCreateViewHolder()用来创建ViewHolder *实例,然后把fruit_item布局加载进来,创建一个VIewHolder实例,并把加载进来的布局传入到 *构造函数中,最后将ViewHolder实例返回。onBindViewHolder()方法是用来对RecyclerView子 *项中的数据进行赋值,会在每个子项被滚动到屏幕内的时候执行,这里通过positon参数得到当前项 *的Fruit实例,再将数据设置到ViewHolder的ImageView和TextView当中,getItemCount()用来返回 *数据源的长度 **/ @Override public 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; } @Override public void onBindViewHolder(ViewHolder holder,int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); } @Override public int getItemCount(){ return mFruitList.size(); } }
最后修改MainActivity,在这里用了一个同样的initFruits()方法,用于初始化所有的水果数据,接着在onCreate()方法中获取到RecyclerView实例,然后创建一个LinearLayoutManager对象。LayoutManager用于指定RecyclerView的布局方式,LinearLayoutManager是线性布局的意思,接下来创建FruitAdapter的实例,并将水果数据传入到FruitAdapter的构造函数中,最后调用RecyclerView的setAdapter()方法来完成适配器设置。
package com.example.recyclerviewtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.LayoutInflater; import android.widget.LinearLayout; import java.util.ArrayList; import java.util.List; import java.util.Random; public class MainActivity extends AppCompatActivity { private List fruitList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化水果数据 initFruits(); 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); } private void initFruits(){ for (int i = 0; i < 2; i++){ Fruit apple = new Fruit( ("Apple"),R.mipmap.ic_launcher); fruitList.add(apple); Fruit banner = new Fruit( ("Banner"),R.mipmap.ic_launcher); fruitList.add(banner); Fruit pear = new Fruit( ("Pear"),R.mipmap.ic_launcher); fruitList.add(pear); Fruit watermalon = new Fruit( ("Watermalon"),R.mipmap.ic_launcher); fruitList.add(watermalon); Fruit cherry = new Fruit( ("Cherry"),R.mipmap.ic_launcher); fruitList.add(cherry); } } }
运行一下,可以看到和ListView一样的效果
二、横向滚动
首先对fruit_item布局进行修改,把元素改为垂直排列
这里要设定宽度,因为文字长度不一的话很难看,使用layout_marginTop属性让文字和图片之间保持距离。
接下来修改MainActivity中的代码,因为LinearLayoutManger.HORIZONTAL是默认纵向排列的,我们要设为横向滚动只需要设置为LinearLayoutManager.HORIZONTAL
package com.example.recyclerviewtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.LayoutInflater; import android.widget.LinearLayout; import java.util.ArrayList; import java.util.List; import java.util.Random; public class MainActivity extends AppCompatActivity { private List fruitList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化水果数据 initFruits(); 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); } private void initFruits(){ for (int i = 0; i < 2; i++){ Fruit apple = new Fruit( ("Apple"),R.mipmap.ic_launcher); fruitList.add(apple); Fruit banner = new Fruit( ("Banner"),R.mipmap.ic_launcher); fruitList.add(banner); Fruit pear = new Fruit( ("Pear"),R.mipmap.ic_launcher); fruitList.add(pear); Fruit watermalon = new Fruit( ("Watermalon"),R.mipmap.ic_launcher); fruitList.add(watermalon); Fruit cherry = new Fruit( ("Cherry"),R.mipmap.ic_launcher); fruitList.add(cherry); } } }
最后运行一下就可以看到横向布局了
当然,GiridLayoutManager可以用于实现网格布局,StaggeredGirdLayoutManager可以实现瀑布流布局
三、瀑布流布局
最后来看看瀑布流布局,首先修改一下fruit_item.xml中的代码
这里我们为了好看把TextView的对齐属性改为居左对齐,因为待会文字会变长
接着来修改MainActivity中的代码
package com.example.recyclerviewtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; 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 fruitList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化水果数据 initFruits(); RecyclerView recyclerView = findViewById(R.id.recycler_view); /** *创建StaggeredGridLayoutManager实例,StaggeredGridLayoutManager *构造函数接收两个参数,第一个参数用于指定布局的列数,表示把布局分为3列, *第二个参数表示指定布局的排列方向 **/ 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.mipmap.ic_launcher); fruitList.add(apple); Fruit banner = new Fruit getRandomLengthName("Banner"),R.mipmap.ic_launcher); fruitList.add(banner); Fruit pear = new Fruit( getRandomLengthName("Pear"),R.mipmap.ic_launcher); fruitList.add(pear); Fruit watermalon = new Fruit( getRandomLengthName("Watermalon"),R.mipmap.ic_launcher); fruitList.add(watermalon); Fruit cherry = new Fruit( getRandomLengthName("Cherry"),R.mipmap.ic_launcher); fruitList.add(cherry); } } 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(); }
因为瀑布流布局需要各个子项高度不一致才能看出明显效果,这里使用getRandLengthName()方法把名字随机重复几遍,这样保证各水果的名字长短不一样
最后运行,可以看到效果
四、设置监听器
当然,我们还可以加上点击事件,不过要注意的是,RecyclerView并没有提供类似于setOnItemClickListener()这样的注册监听器方法,需要我们自己给子项具体的View去注册点击事件
修改FruitAdapter.java
package com.example.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 { private List 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 fruitList){ mFruitList = fruitList; } @Override public 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(),"你点击了文字"+fruit.getName(), Toast.LENGTH_LONG).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(),"你点击了图片" + fruit.getName(), Toast.LENGTH_LONG).show(); } }); // ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(ViewHolder holder,int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); } @Override public int getItemCount(){ return mFruitList.size(); } }
我们在ViewHolder中加入了fruitView变量来保存子项最外层布局的实例,然后在onCreateViewHolder()方法中注册点击事件就可以了
我们会看到,点击文字和点击图片是弹出不同的内容的
相关推荐
0评论