Lập trình Android – Bài 11: ListView trong Android

Qua 2 bài lý thuyết trước đó chắc các bạn đã có cái nhìn tổng quan hơn, hôm nay chúng ta quay trở lại với code với bài ListView.
ListView giống như tên gọi của nó, List là danh sách, View là hiển thị, tức là hiển thị danh sách. Nếu bạn đã dùng điện thoại Android thì bạn sẽ nhìn thấy nó ở khắp mọi nơi, từ danh bạ, danh sách bạn bè, danh sách chat,… đều là ListView cả.

[qads]

Trong bài này, mình sẽ hướng dẫn các bạn tạo các ListView đơn giản nhất, ListView phức tạp sẽ để bài sau. Trước tiên chúng ta tạo ứng dụng gồm danh sách các bài học mà chúng ta đã học như hình sau:

android-listview-3

Các bạn tạo project Với Empty Activity nhé.

Cách 1: Tạo danh sách từ mảng

Trước tiên chúng ta thiết kế giao diện đã. Giao diện của ListView rất đơn giản, chúng ta chỉ cần có đối tượng ListView là xong.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.nguyenvanquan7826.tut11listview.MainActivity">

    <ListView
        android:id="@+id/lvTUT"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Khi các bạn đặt id cho ListView thì chúng ta sẽ có giao diện xem trước như sau:
android-listview-1

Trong giao diện trên, mỗi một Item là 1 phần tử của ListView khi chạy, ở đây họ chỉ mô tả cho chúng ta biết ListView sẽ hiển thị như vậy, chứ thực chất chúng ta chưa có dữ liệu về các phần tử trong danh sách nhé.

Tiếp theo các bạn mở file res/values/string.xml ra và thêm như sau:

<resources>
    <string name="app_name">TUT11ListView</string>

    <string-array name="tut_android">
        <item>Bài 1: Hello World</item>
        <item>Bài 2: TextView, EditText, Button</item>
        <item>Bài 3: Bắt sự kiện click Button</item>
        <item>Bài 4: Thiết kế giao diện với RelativeLayout</item>
        <item>Bài 5: Thiết kế giao diện với LinearLayoout</item>
        <item>Bài 6: Thực hành xây dựng ứng dụng Calculator</item>
        <item>Bài 7: Toast, CheckBox, RadioButton, Dialog</item>
        <item>Bài 8: Intent – Chuyển đổi giữa các màn hình</item>
        <item>Bài 9: Cấu trúc Project</item>
        <item>Bài 10: Vòng đời Activity</item>
    </string-array>
</resources>

Ở đây, thẻ string-array là thẻ cho phép chứa danh sách các chuỗi, mỗi chuỗi đặt trong một thẻ item.

Bây giờ là thời điểm code java để đưa dữ liệu trên hiển thị lên ListView.

package com.nguyenvanquan7826.tut11listview;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    private ListView lvTut;
    private String[] listData;
    private ArrayAdapter<String> adapter;

    private Context context;

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

        context = this;

        connectView();
        loadData();
    }

    private void connectView() {
        lvTut = (ListView) findViewById(R.id.lvTUT);
    }

    private void loadData() {
        // get data (string array) from xml file
        listData = context.getResources().getStringArray(R.array.tut_android);

        // create adapter with listData and layout item
        adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, listData);

        lvTut.setAdapter(adapter);
    }
}

Trong code bên trên, các bạn chú ý dòng tạo adapter, chúng ta có 3 đối số là Context (ngữ cảnh), layout, và listData. Trong đó layout là android.R.layout.simple_list_item_1 là một file do hệ thống có sẵn để hiển thị 1 dòng chữ và chúng ta thường dùng nó cho các danh sách đơn giản.

Dòng lấy mảng chuỗi từ file xml sẽ trả về cho chúng ta một String[], do vậy ngoài các đưa chuỗi vào file xml, chúng ta có thể gán trực tiếp mảng chuỗi tại đây và chúng ta có thể viết như sau:

private void loadData() {
    listData = new String[] {
            "Bài 1: Hello World",
            "Bài 2: TextView, EditText, Button",
            "Bài 3: Bắt sự kiện click Button"
    };

    // create adapter with listData and layout item
    adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, listData);

    lvTut.setAdapter(adapter);
}

Cách 2: Tạo danh sách từ ArrayList

ArrayList là một thành phần chúng ta dùng nhiều nhất với ListView nhất là khi danh sách của chúng ta luôn luôn biến đổi. Code dưới đây sẽ minh họa cách dùng ArrayList.

package com.nguyenvanquan7826.tut11listview;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ListView lvTut;
    private ArrayList<String> listData;
    private ArrayAdapter<String> adapter;

    private Context context;

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

        context = this;

        connectView();
        loadData();
    }

    private void connectView() {
        lvTut = (ListView) findViewById(R.id.lvTUT);
    }

    private void loadData() {

        listData = new ArrayList<>();
        listData.add("Bài 1: Hello World");
        listData.add("Bài 2: TextView, EditText, Button");
        listData.add("Bài 3: Bắt sự kiện click Button");
        listData.add("Bài 4: Thiết kế giao diện với RelativeLayout");
        listData.add("Bài 5: Thiết kế giao diện với LinearLayoout");

        // create adapter with listData and layout item
        adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, listData);

        lvTut.setAdapter(adapter);
    }

}

Kết quả bạn nhận được sẽ không khác gì so với làm bằng mảng cả. Tuy nhiên ở đây mình muốn đề cập tới các bạn tính linh động khi thêm bớt phần tử trong danh sách. Để thực hiện được điều này các bạn tiếp tục sửa giao diện như sau nhé.

android-listview-add-item

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.nguyenvanquan7826.tut11listview.MainActivity">

    <EditText
        android:id="@+id/editTut"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/btnAdd"
        android:hint="Enter tut title" />

    <Button
        android:id="@+id/btnAdd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Add" />


    <ListView
        android:id="@+id/lvTUT"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/btnAdd" />
</RelativeLayout>

Khi click vào button Add, chúng ta thực hiện thêm vào danh sách.

package com.nguyenvanquan7826.tut11listview;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ListView lvTut;
    private ArrayList<String> listData;
    private ArrayAdapter<String> adapter;
    
    private EditText editTut;

    private Context context;

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

        context = this;

        connectView();
        loadData();
    }

    private void connectView() {
        lvTut = (ListView) findViewById(R.id.lvTUT);
        editTut = (EditText) findViewById(R.id.editTut);
        findViewById(R.id.btnAdd).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                addTut();
            }
        });
    }

    private void loadData() {

        listData = new ArrayList<>();
        listData.add("Bài 1: Hello World");
        listData.add("Bài 2: TextView, EditText, Button");
        listData.add("Bài 3: Bắt sự kiện click Button");
        listData.add("Bài 4: Thiết kế giao diện với RelativeLayout");
        listData.add("Bài 5: Thiết kế giao diện với LinearLayoout");

        // create adapter with listData and layout item
        adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, listData);

        lvTut.setAdapter(adapter);
    }
    
    private void addTut(){
        String tut = editTut.getText().toString().trim();
        
        if(TextUtils.isEmpty(tut)) {
            Toast.makeText(context, "Please enter tut title", Toast.LENGTH_SHORT).show();
            return;
        }
        
        listData.add(tut);
        
        // update data to show on listview
        adapter.notifyDataSetChanged();
        
    }

}

Trong code trên các bạn chú ý lệnh adapter.notifyDataSetChanged();, chúng ta gọi nó mỗi khi danh sách dữ liệu của chúng ta có sự thay đổi như thêm vào, xóa đi hoặc sửa phần tử nào đó.

Bắt sự kiện click vào phần tử trong ListView

Chúng ta thường thao tác với các phần tử trong danh sách bằng cách click vào các phần tử đó. Ví dụ click vào một người trong danh bạ để mở xem chi tiết về nguơi đó,… Vậy làm sao để bắt được sự kiện click vào phần tử trong ListView? Bạn chỉ cần setOnItemClickListener cho ListView là xong.

lvTut.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Toast.makeText(context, listData.get(i), Toast.LENGTH_SHORT).show();
        // do something
    }
});

Trong hàm onItemClick các bạn thấy có biến int i, nó là vị trí của phần tử được click trong danh sách của chúng ta đó.

Bài này đến đây xong rồi. Bài sau sẽ khó hơn nên các bạn cần nắm bài này thật chắc vào nhé.