1. 程式人生 > >Android的ListView和RecyclerView的基本用法

Android的ListView和RecyclerView的基本用法

在Android 5.0 版本之前,為了方便的顯示多行資料,形如QQ聊天資訊主介面,最常用的選擇無非是ListView控制元件,但是ListView控制元件本身就有很大的侷限性和效率問題(相對於RecyclerView控制元件)來說,比如說ListView只能豎向滾動顯示資料,不能橫向滾動顯示資料,在一些特殊的需求中,ListView就無能為力了。在Android5.0版本之後,Android官方推出了一個新的控制元件:RecyclerView ,完全解耦的設計使得RecyclerView比起ListView靈活了太多,應用的場合也非常廣泛。那麼,就來看一下ListView和RecyclerView的用法和不同之處在哪:

首先我們先來看一下ListView控制元件的簡單用法,比如說我們現在要顯示這樣一個介面:
這裡寫圖片描述
每一行專案是一個ImageView和TextView控制元件的組合。

新建一個 Android 工程:
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:id
="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal" tools:context="com.example.administrator.listviewandrecycleview.MainActivity">
<ListView android:id="@+id/listView"
android:layout_width="match_parent" android:layout_height="match_parent">
</ListView> </LinearLayout>

在主佈局檔案中,我們添加了一個ListView控制元件,用於接下來的資料顯示,之後我們要新建一個佈局檔案用於顯示ListView中的專案資料 color_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/colorImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/colorNameTextView"
        android:layout_marginLeft="10dp"
        android:textSize="40sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

佈局採用線性橫向佈局,檔案中有兩個控制元件ImageView、TextView。分別用於顯示顏色和文字,有了控制元件,那麼對應儲存資訊的類就有眉目了,新建一個類Color.java:

public class Color {

    private String colorName;
    private int imageId;

    public Color(String colorName, int imageId) {
        this.colorName = colorName;
        this.imageId = imageId;
    }

    public String getColorName () {
        return colorName;
    }

    public int getImageId() {
        return imageId;
    }


}

一個簡單的類,儲存的資訊對應於我們前面佈局檔案中顯示的資訊。

ListView是需要介面卡才能顯示我們定義的佈局檔案的,那麼我們接下來要為ListView設定一個介面卡。這裡採用ArrayAdapter作為基類介面卡,我們新建一個類ColorAdapter來繼承ArrayAdapter,並且加入我們自己的邏輯:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.administrator.listviewandrecycleview.R;

import java.util.List;

import javax.crypto.spec.PSource;

/**
 * Created by Administrator on 2017/2/21.
 * 自定義介面卡類繼承於 ArrayAdapter 類來實現 ListView 控制元件的資料顯示,
 * ListView 控制元件只有設定了介面卡才能顯示資料
 */

public class ColorAdapter extends ArrayAdapter {

    private int itemLayoutId;

    public ColorAdapter(Context context, int itemLayoutId, List<Color> objects) {
        super(context, itemLayoutId, objects);
        this.itemLayoutId = itemLayoutId;
    }

    /*
     * getView方法用於返回ListView中的item 的檢視
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Color color = (Color) getItem(position);
        View view;
        /*
         * convertView 引數用於儲存之前載入好的佈局快取,如果不為空,那麼我們可以直接用這個用來給view賦值
         * 提高ListView的執行效率
         */
        if(convertView != null) {
            view = convertView;
        }else {
            /*
             * 載入自定義的佈局檔案,這個方法用於載入佈局檔案,並且返回一個 View 物件。
             * 這樣我們就能夠在程式碼中使用佈局檔案中的各個屬性。
             * 這裡的 inflate 方法的三個引數分別代表:
             * 要載入的佈局檔案Id、為載入的佈局檔案外層再加一層父佈局、第三個引數如果為 true 的話就是把載入的 View 加入父佈局中作為子控制元件。否則就是隻在父佈局中宣告,不新增進入父佈局
             * 這裡我們當然不能加入父佈局,因為我們的 View 是要加入 ListView 中作為子控制元件的
             */
            view = LayoutInflater.from(getContext()).inflate(itemLayoutId, parent, false);
        }
        // 獲取佈局檔案中的控制元件id並且顯示對應資訊:
        ImageView imageView = (ImageView) view.findViewById(R.id.colorImageView);
        TextView textView = (TextView) view.findViewById(R.id.colorNameTextView);
        imageView.setImageResource(color.getImageId());
        textView.setText(color.getColorName());
        return view;
    }
}

在ColorAdapter.java中,我們重寫了ArrayAdapter類中的getView方法返回的View作為ListView中的item檢視。ok,最後是MainActivity.java:


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.ListViewCompat;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

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

import listview.Color;
import listview.ColorAdapter;

public class MainActivity extends AppCompatActivity {

    private String colorName[] = new String[]{
            "blue", "colors", "green", "pink", "puple", "yellow"};
    private int colorId[];
    private static final int colorSum = 6;
    List<Color> list = new ArrayList<Color>();
    private ColorAdapter colorAdapter = null;
    private ListView listView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initAdapter();
        listView = (ListView) findViewById(R.id.listView);
        listView.setAdapter(colorAdapter); // 為listView設定介面卡

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // 設定ListView的點選響應事件
            /*
             * listView的點選事件:第一個引數是item所在的介面卡引用,
             * 第二個引數是點選的item的View物件,在這裡這個View包含了一個ImageView和一個TextView
             * (佈局檔案color_item佈局檔案中的控制元件)
             * 第三個和第四個引數一般是一樣的,代表你點選的item在ListView中的位置
             */
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Color color = (Color) list.get(position); // 獲取點選的View 中包含的Color 物件
                Toast.makeText(MainActivity.this, "顏色名稱:" + color.getColorName(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    protected void initAdapter() {
        colorAdapter = new ColorAdapter(this, R.layout.color_item, list);

        colorId = new int[]{R.mipmap.blue, R.mipmap.colors, R.mipmap.green, R.mipmap.pink,
                                R.mipmap.puple, R.mipmap.yellow};
        for(int i = 0; i < colorSum; i++) {
            Color color = new Color(colorName[i], colorId[i]);
            list.add(color);
        }
    }
}

在MainActivity.java中我們用一個initAdapter方法來初始化ListView需要顯示的資料資訊,之後將資料資訊加入ColorAdapter物件中並且設定ListView控制元件的介面卡為ColorAdapter物件。基本的步驟就完成了,讓我們來看一下效果:
這裡寫圖片描述

ListView簡單的用法就是這樣了。我們在實際使用的時候可以根據我們自己的需求來設定ListView控制元件的item佈局檔案和ListView的點選事件處理。

那麼接下來我們來看一下RecyclerView控制元件的簡單用法:我們先用RecyclerView控制元件來實現上面的功能,你可以選擇新建一個Android工程,也可以在上面的ListView控制元件中的工程中加一個Activity來顯示RecyclerView,筆者這裡選擇的是新建一個Activity來顯示RecyclerView:
因為RecyclerView是在android5.0版本新增在support.v7庫中,並不是在SDK中,所以我們要進行依賴宣告:在app中的build.gradle檔案中加入以下程式碼:

compile 'com.android.support:recyclerview-v7:25.1.1'

並且點選螢幕右上方的sync now,如下圖:
這裡寫圖片描述
這裡我用的是android studio IDE 個人感覺android studio 相比eclipse在android開放方面好,不過android studio 對電腦效能要求更加高。
好了我們還要知道,RecyclerView控制元件的介面卡必須繼承於RecyclerView.Adapter<RecyclerView.ViewHolder> 類並且重寫其中的抽象方法,那麼我們新建一個介面卡類用來適配要在RecyclerView控制元件中顯示的資料:ColorAdapterForRecyclerView.java:

import android.content.Context;
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 com.example.administrator.listviewandrecycleview.MainActivity;
import com.example.administrator.listviewandrecycleview.R;
import java.util.List;

/**
 * Created by Administrator on 2017/2/21.
 */

public class ColorAdapterForRecyclerView extends RecyclerView.Adapter<ColorAdapterForRecyclerView.MyViewHolder> {

    private List<Color> colorList = null;
    private Context myContext = null; // Context物件作為Toast提示的第一個引數

    /*
     * 新建一個靜態內部類MyViewHolder繼承於RecyclerView.ViewHolder,根據java多型的特性,
     * 我們在上面的泛型引數就可以傳入這個類作為引數
     */
    static class MyViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;
        TextView textView;

        public MyViewHolder(View view) {
            super(view);
            imageView = (ImageView) view.findViewById(R.id.colorImageView);
            textView = (TextView) view.findViewById(R.id.colorNameTextView);
        }
    }

    public ColorAdapterForRecyclerView(Context context, List<Color> colorList)  {
        myContext = context;
        this.colorList = colorList;
    }

    /*
     * 重寫父類的onCreateViewHolder方法,用於建立MyHolder物件作為RecyclerView的顯示子項
     * 每個 RecyclerView 控制元件的 item 呼叫這個方法之後呼叫
     *  onBindViewHolder 方法之後才能作為一個子項顯示在 RecyclerView 控制元件中
     */
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.color_item, parent, false);
        /*
         * 為每一個RecyclerView中顯示的子項設定點選處理事件
         */
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TextView textView = (TextView) v.findViewById(R.id.colorNameTextView);
                Toast.makeText(myContext, "顏色名稱:" + textView.getText().toString(), Toast.LENGTH_SHORT).show();
                }
        });
        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    /*
     * 重寫父類的onBinderViewHolder方法,用於對RecyclerView中顯示在螢幕中的子項設定對應的資料資訊
     */
    @Override
    public void onBindViewHolder(MyViewHolder myViewHolder, int position) {
        Color color = colorList.get(position);
        myViewHolder.imageView.setImageResource(color.getImageId());
        myViewHolder.textView.setText(color.getColorName());
    }

    /*
     * 重寫父類的getItemCount方法用於返回RecyclerView中一共有多少子項
     */
    @Override
    public int getItemCount() {
        return colorList.size();
    }

}

好了,RecyclerView的介面卡已經寫好了,接下來我們新建一個佈局檔案recycler_view_activity.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:id="@+id/activity_recycle_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context="com.example.administrator.listviewandrecycleview.RecycleViewActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>

</LinearLayout>

這個佈局檔案就是加入了一個RecyclerView控制元件,注意我們在使用不是SDK中原本就存在的控制元件時,要寫入這個控制元件的完整路徑名(包括我們自定義的控制元件),接下來新建一個Activity用於顯示RecyclerView,RecyclerViewActivity.java:


import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import listview.Color;
import listview.ColorAdapterForRecyclerView;

public class RecyclerViewActivity extends AppCompatActivity {

    private RecyclerView recyclerView = null;
    private String colorName[];
    private int colorId[];
    private static final int colorSum = 6;
    List<Color> colorList = new ArrayList<Color>();
    private ColorAdapterForRecyclerView colorAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycle_view);

        initAdapter(); // 初始化資訊,和ListView中的類似,只是介面卡的型別不同
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        /*
         * 因為RecyclerView只負責自己本身的建立和回收,所以RecyclerView中的子項建立、子項佈局方式、
         * 分割線、動畫效果等等都需要我們自己完成,正是這種完全解耦的機制成就了RecyclerView控制元件的
         * 靈活性,裡面的東西完全由我們自己的需求來編輯邏輯完成
         */
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager); // 設定佈局方式為線性佈局,預設為豎向佈局
        recyclerView.setAdapter(colorAdapter);
    }

    protected void initAdapter() {
        colorAdapter = new ColorAdapterForRecyclerView(this, colorList);
        colorName = new String[]{
                "blue", "colors", "green", "pink", "puple", "yellow"};
        colorId = new int[]{R.mipmap.blue, R.mipmap.colors, R.mipmap.green, R.mipmap.pink,
                R.mipmap.puple, R.mipmap.yellow};
        for (int i = 0; i < colorSum; i++) {
            Color color = new Color(colorName[i], colorId[i]);
            colorList.add(color);
        }
    }
}

好了,大體上的程式碼我們都完成了,最後在主介面加一個按鈕用於啟動RecyclerViewActivity就行了。下面看執行結果:
這裡寫圖片描述
這裡依然是MainActivity中的顯示,多了一個按鈕用於啟動RecyclerViewActivity。我們點選這個按鈕:
這裡寫圖片描述
啟動了RecyclerViewActivity之後點選“green”那一行(單擊別的行也是可以的),成功顯示了我們設定的事件資訊。那麼接下來如何顯示橫向的滾動View呢,其實很簡單:只需要在RecyclerViewActivity中加一句程式碼:

        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 設定控制元件內排布方式為水平

如圖:
這裡寫圖片描述

我們還需要對color_item.xml檔案進行修改

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_marginLeft="20dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/colorImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/colorNameTextView"
        android:layout_marginLeft="10dp"
        android:textSize="40sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

其實就是把排布方式改為該為豎直方向,使得排版更加美觀。好了,再試試:
這裡寫圖片描述
成功了,我們可以左右滑動來顯示不同的子項。那麼如果要顯示網狀佈局呢?其實也很簡單,我們只需要改RecyclerView的佈局管理型別為網狀佈局就行了:

/*
* 設定網狀佈局管理器,每一行3個子項,排布方式為豎直方向排布
 */
StaggeredGridLayoutManager staggeredGriadLayoutManager = new StaggeredGridLayoutManager(
                                            3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGriadLayoutManager);

如圖:
這裡寫圖片描述
來看看效果:
這裡寫圖片描述
ok,和我們預想的一樣

最後,這裡只是RecyclerView控制元件的基本用法,RecyclerView控制元件的用法很多,我們可以自由的在控制元件裡面加入分割線,子項減少和增加的動畫效果等等,我們可以自由的定製屬於我們的效果。有興趣的小夥伴可以看一下這篇博文:為RecyclerView 控制元件新增分隔線:http://blog.csdn.net/hacker_zhidian/article/details/57487844

如果部落格中有什麼不正確的地方,還請多多指點。
謝謝觀看。。。