列表控制項 ListView-基本用法
這是一個非常常用的控制項。
我們的螢幕空間有限,但透過這個控制項,可以在畫面上顯示更多資料。
用手指上下滑動,就能把畫面外的資料帶入畫面中。
基本用法
建立一個 TestListView 專案。
在檢視中加入以下程式碼,加入 ListView。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listview1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>Code language: HTML, XML (xml)
初始化資料來源
public class MainActivity extends AppCompatActivity {
private String[] courses = {"Java 入門", "Android 入門", "C# 入門", "C 語言", "ASP.NET MVC"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, courses);
ListView listView = (ListView) findViewById(R.id.listview1);
listView.setAdapter(adapter);
}
}Code language: JavaScript (javascript)
這些資料可以從網路下載(例如透過 Web API)、從資料庫讀取,甚至直接在程式碼中定義字串陣列。
資料無法直接傳遞給 ListView,需要透過介面卡(Adapter)來協助。
Android 提供了許多介面卡,這裡我們使用 ArrayAdapter。
我們使用 android.R.layout.simple_list_item_1 作為 ListView 的子版面配置。
這是 Android 內建的版面配置檔案,只有一個 TextView 用來顯示一段文字。

列表控制項 ListView-自訂介面
如果只顯示一段文字,似乎太過簡單
我們可以在列表項目中顯示更豐富的內容。
新增一個 Book 實體類別
package com.foxdevelop.www.testlistview;
public class Book {
private String name;
private int imageId;
public Book (String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
}Code language: PHP (php)
新增一個 book 的檢視檔案
<?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="match_parent">
<ImageView
android:id="@+id/imageid"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="12dp"
/>
</LinearLayout>Code language: HTML, XML (xml)
自訂介面卡
package com.foxdevelop.www.testlistview;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
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 java.util.List;
public class BookAdapter extends ArrayAdapter<Book> {
private int resource;
public BookAdapter(@NonNull Context context, int resource, @NonNull List<Book> objects) {
super(context, resource, objects);
this.resource = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Book book = getItem(position);
View view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
ImageView imageView = (ImageView) view.findViewById(R.id.imageid);
imageView.setImageResource(book.getImageId());
TextView name = (TextView) view.findViewById(R.id.name);
name.setText(book.getName());
return view;
}
}Code language: JavaScript (javascript)
在活動的 onCreate 中初始化資料來源
package com.foxdevelop.www.testlistview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List<Book> courses = new ArrayList<Book>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoadBooks();
BookAdapter adapter = new BookAdapter(MainActivity.this, R.layout.booklistview, courses);
ListView listView = (ListView) findViewById(R.id.listview1);
listView.setAdapter(adapter);
}
private void LoadBooks() {
courses.add(new Book("人類思想史上第一", R.drawable.access));
courses.add(new Book("剝削階段政治", R.drawable.book));
courses.add(new Book("印度古代法律的珍貴文獻", R.drawable.bookmarks));
courses.add(new Book("欽定羅馬私法教科書", R.drawable.center));
courses.add(new Book("知識就是力量", R.drawable.date));
courses.add(new Book("我的民法典會永遠存在", R.drawable.clock));
courses.add(new Book("研究美國民主的經典之作", R.drawable.ftp));
courses.add(new Book("西方國際法權威教材", R.drawable.notes));
courses.add(new Book("最貼近歷史真實的力作", R.drawable.set));
courses.add(new Book("宗教改革的一面鏡子", R.drawable.energy));
courses.add(new Book("神學的祕密就是人本學", R.drawable.tux));
courses.add(new Book("三百多年前就介紹到了中國的名", R.drawable.science));
courses.add(new Book("刻畫偽君子的千古傑作", R.drawable.joystick));
courses.add(new Book("沒有圍牆的名牌大學", R.drawable.center));
courses.add(new Book("人類思想史上第一個烏托邦方案", R.drawable.access));
}
}Code language: JavaScript (javascript)
透過設定
android:orientation=”horizontal”
可以讓它橫向排列。


最佳化 ListView 效能
目前每次開啟活動都會重新載入資料來源,這會影響執行效率。透過快取 View,我們可以提升速度。
透過判斷 convertView,我們不需要每次都重新取得 view。
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Book book = getItem(position);
View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
} else {
view = convertView;
}
ImageView imageView = (ImageView) view.findViewById(R.id.imageid);
imageView.setImageResource(book.getImageId());
TextView name = (TextView) view.findViewById(R.id.name);
name.setText(book.getName());
return view;
}Code language: PHP (php)
快取控制項
定義一個類別來存放圖片控制項和文字控制項。
class ViewData {
ImageView imageUI;
TextView textViewUI;
}Code language: JavaScript (javascript)
package com.foxdevelop.www.testlistview;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
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 java.util.List;
public class BookAdapter extends ArrayAdapter<Book> {
private int resource;
public BookAdapter(@NonNull Context context, int resource, @NonNull List<Book> objects) {
super(context, resource, objects);
this.resource = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Book book = getItem(position);
View view;
ViewUI viewUI;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
ImageView imageView = (ImageView) view.findViewById(R.id.imageid);
TextView textView = (TextView) view.findViewById(R.id.name);
viewUI = new ViewUI();
viewUI.imageUI = imageView;
viewUI.textViewUI = textView;
view.setTag(viewUI);
} else {
view = convertView;
viewUI = (ViewUI) view.getTag();
}
viewUI.imageUI.setImageResource(book.getImageId());
viewUI.textViewUI.setText(book.getName());
return view;
}
class ViewUI {
ImageView imageUI;
TextView textViewUI;
}
}Code language: JavaScript (javascript)
ListView 點擊事件
為 listview 中的項目加入點擊事件。
例如,我們實作點擊每一項時顯示書本名稱。
在主活動的 onCreate 裡:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoadBooks();
BookAdapter adapter = new BookAdapter(MainActivity.this, R.layout.booklistview, courses);
final ListView listView = (ListView) findViewById(R.id.listview1);
listView.setAdapter(adapter);
// 點擊事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Book b = courses.get(i);
Toast.makeText(MainActivity.this, b.getName(), Toast.LENGTH_LONG).show();
}
});
}Code language: PHP (php)
在 gradle 的 dependencies 中加入依賴函式庫
Configuration ‘compile’ is obsolete and has been replaced with ‘implementation’ and ‘api’.
它將在 2018 年底被移除。更多資訊請參閱:http://d.android.com/r/tools/update-dependency-configurations.html
我們需要加入對
android.support.v7.widget.RecyclerView
依賴函式庫的支援。

<?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/testrecy"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>Code language: HTML, XML (xml)
捲動控制項 RecyclerView 的使用-1
ListView 很強大,應用非常廣泛,至今仍有許多應用程式在使用。
不過它的效能稍差,擴充性也不強。
只能實作資料縱向捲動,無法橫向捲動。
RecyclerView 是 ListView 的強化版。
它可以實作與 ListView 相同的效果,並且最佳化了 ListView。
官方推薦使用 RecyclerView。
基本用法
首先,請先在 gradle 中加入:
compile ‘com.android.support:recyclerview-v7:27.1.1’
上一節中,我們加入了另一個 RecyclerView。
<android.support.v7.widget.RecyclerView
android:id="@+id/testrecy"
android:layout_width="match_parent"
android:layout_height="match_parent"/>Code language: HTML, XML (xml)
我們繼續使用書本的例子。