RecyclerView控件講解(實現縱向/橫向滾動以及瀑布流佈局)

與ListView對比優勢:

  1.運行效率更高。

  2.能實現橫向滾動與瀑布流佈局。

  官方更加推薦Recycler控件,但因爲後期加入又要使所有版本的Android都能使用,所以把它放入了support庫當中,所以使用的第一步,是在項目的build.gradle中添加相應的依賴庫。

打開app/build.gradle文件,在dependencies中添加

implementation 'com.android.support:recyclerview-v7:28.0.0'

不同項目不同版本的依賴庫版本號不同,截圖給大家參考下我現在的,不必模仿:

點擊Sync Now同步。

  那麼如何使用這個控件呢?點擊activity_main.xml,修改代碼:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>

中間的這段代碼,就是調用RecyclerView控件。因爲它並不是內置在SDK中的控件,所以使用時要寫出完整的路徑名。

接下來我們以水果列表顯示爲例分別實現四個功能,每個功能講解結束都會附上Demo,請自行下載:

1:實現縱向滾動

2:實現橫向滾動

3:實現瀑布流佈局

4:實現recyclerView點擊事件

功能一:實現縱向滾動

  先創建一個Fruit類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。

<?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="wrap_content">

    <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>

接下來爲RecyclerView準備一個適配器,新建FruitAdapter類文件FruitAdapter.java,讓這個個適配器繼承自RecyclerView.Adapter,並將泛型指定爲FruitAdapter.ViewHolder。其中ViewHolder是我們在FruitAdapter中定義的一個內部類,代碼如下:

package com.example.recyclerviewtest;

import android.media.Image;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import org.w3c.dom.Text;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private List<Fruit> mFruitList;

    //傳入view參數,這個參數就是RecyclerView的子項佈局,這樣就能找到裏面各個控件的id
    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            fruitImage = (ImageView)itemView.findViewById(R.id.fruit_image);
            fruitName = (TextView)itemView.findViewById(R.id.fruit_name);
        }
    }

    //將要展示的數據源傳入
    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    //下面三個函數必須要重寫

    //載入fruit_item佈局,創建ViewHolder實例
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    //爲每個RecylerView對象賦值
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit.getName());
        holder.fruitImage.setImageResource(fruit.getImageId());
    }

    //計算一共多少個子項
    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}

適配器已經準備好了,我們現在可以使用RecyclerView了,修改MainActivity.java:

package com.example.recyclerviewtest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        //獲取recyclerView實例
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        //創建LinerLayoutManager對象,其中LayoutManager用於指定RecyclerView的佈局方式
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //設置佈局
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //關聯RecyclerView與數據
        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);
        }
    }
}

接下來就可以運行了,以後如果需要不同的內容,結構,更改部分代碼即可,代碼結構不會改變。下面是運行效果:

功能一Demo文件下載:https://download.csdn.net/download/qq_38367681/12167275

功能二:實現橫向滾動

  要實現橫向拉動其實很簡單,因爲ListView的佈局是由自身去管理的,而RecyclerView把這個工作交給了LayoutManager,LayoutManager中制定了一套可擴展的佈局排列接口,子類只要按照接口的規範來實現,就能定製出各種不同排列的佈局了。

  第一步,肯定要先改寫子項的佈局,使它橫向排列看起來更舒服,所以修改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>

第二部,只需要調整layoutManager的排列方向。默認是垂直方向,所以縱向排列的代碼並沒有加入方向調整,實現功能二,我們只需要加入一行代碼,設置排列方向爲水平:

layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

所以MainActivity.java代碼變成如下:

package com.example.recyclerviewtest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        //獲取recyclerView實例
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        //創建LinerLayoutManager對象,其中LayoutManager用於指定RecyclerView的佈局方式
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //設置線性佈局爲水平線性佈局,默認爲垂直,所以不設置效果會跟listview一樣
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        //設置佈局
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //關聯RecyclerView與數據
        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);
        }
    }
}

運行結果如下:

功能二Demo文件下載:https://download.csdn.net/download/qq_38367681/12168921

功能三:實現瀑布流佈局

  同功能二,爲了瀑布流佈局更美觀,肯定是先修改fruit_item.xml文件,然後再修改MainActivity.java中的LayoutManager,使其變成瀑布流佈局。當然也只是一行代碼:

StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
共接收兩個參數,第一個參數是列數,第二個參數是佈局的排列方向。

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="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp">

    <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="left"
        android:layout_marginTop="10dp"/>

</LinearLayout>

MainActivity.java代碼如下:

package com.example.recyclerviewtest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import android.os.Bundle;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        //獲取recyclerView實例
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        //創建一個StaggeredGridLayoutManager實例,共接收兩個參數,第一個參數是列數,第二個參數是佈局的排列方向
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        //設置佈局
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //關聯RecyclerView與數據
        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("BananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBanana", 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("GrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrape", 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);
        }
    }
}

運行結果如下:

功能三Demo文件下載:https://download.csdn.net/download/qq_38367681/12169036

功能四:RecyclerView的點擊事件。

  RecyclerView所有的點擊事件都需要具體的View控件去註冊,其實這樣反而會更舒服,我們可以爲任何我們想要觸發點擊事件的控件,佈局,甚至是RecyclerView列表子項添加點擊事件。爲RecyclerView子項添加點擊監聽時,我們在ViewHolder中添加fruitView變量用來保存子項最外層的佈局實例,然後在onCreateViewHolder()方法中註冊點擊事件即可。爲子項的控件添加點擊監聽時,直接用viewholder裏的佈局控件註冊點擊即可。代碼如下:

FruitAdapter.java

package com.example.recyclerviewtest;

import android.media.Image;
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 androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import org.w3c.dom.Text;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private List<Fruit> mFruitList;

    //傳入view參數,這個參數就是RecyclerView的子項佈局,這樣就能找到裏面各個控件的id
    static class ViewHolder extends RecyclerView.ViewHolder {
        //整個子項佈局
        View fruitView;

        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            fruitView = itemView;
            fruitImage = (ImageView)itemView.findViewById(R.id.fruit_image);
            fruitName = (TextView)itemView.findViewById(R.id.fruit_name);
        }
    }

    //將要展示的數據源傳入
    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    //下面三個函數必須要重寫

    //載入fruit_item佈局,創建ViewHolder實例
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull 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;
    }

    //爲每個RecylerView對象賦值
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit.getName());
        holder.fruitImage.setImageResource(fruit.getImageId());
    }

    //計算一共多少個子項
    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}

運行結果如下:

點擊圖片時 

當點擊文字(其實代表的是圖片文字整個子項被點擊,因爲給圖片註冊了點擊監聽,所以只能點文字表明點擊了整個子項)

功能四Demo文件下載:https://download.csdn.net/download/qq_38367681/12169120

直接複製使用吧,祝愉快

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章