用RecyclerView实现纵向滚动、横向滚动和瀑布流布局

我们知道,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一样的效果
用RecyclerView实现纵向滚动、横向滚动和瀑布流布局_第1张图片

二、横向滚动

首先对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);
        }
    }




}

用RecyclerView实现纵向滚动、横向滚动和瀑布流布局_第2张图片
最后运行一下就可以看到横向布局了
当然,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实现纵向滚动、横向滚动和瀑布流布局_第3张图片

四、设置监听器

当然,我们还可以加上点击事件,不过要注意的是,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()方法中注册点击事件就可以了

我们会看到,点击文字和点击图片是弹出不同的内容的
用RecyclerView实现纵向滚动、横向滚动和瀑布流布局_第4张图片

你可能感兴趣的:(Android,studio学习笔记)