Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về Material Design, một số nguyên lý cơ bản của nó, và cách tích hợp nó vào trong ứng dụng Android, cũng như các coding convention dành riêng cho Android mà Kteam cho là khá hiệu quả.
Và ở bài này, chúng ta sẽ cùng đến một phần khác mà các bạn nghe đến đã yêu luôn: Hiển thị danh sách.
Rồi hẳn có bạn sẽ nói: “Hư cấu! Danh sách thì có gì mà yêu”.
Có đấy, nhiều là đằng khác. Nào, xin mời!
Đọc hiểu bài này tốt nhất
Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về các phần:
- Cấu trúc cơ bản của một ứng dụng Android.
- Biết Activity là gì?
- Biết sử dụng mảng (array) hoặc danh sách (List) trong Java. Cái này rất quan trọng.
Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:
- Các cách hiển thị danh sách trên ứng dụng Android.
- ListView là… cái gì?
- Cách hiển thị một danh sách đơn giản, toàn chữ.
- Cách hiển thị một danh sách phức tạp hơn một chút, bao gồm 2 dòng và 1 biểu tượng.
ListView là cái gì?
ListView là một View đặc biệt. Ấy ấy nếu bạn chưa biết View là gì thì hãy đọc qua bài “Các thành phần giao diện cơ bản” đã nhé.
Đặc biệt là sao? Là ListView có thể hiển thị một danh sách nào đó.
Hẳn sẽ có nhiều bạn nghĩ đơn giản: “Ùi dào ôi, nếu muốn hiển thị n phần tử thì tạo ra n cái View là xong chứ gì?”
Không, đừng làm vậy. Đã là lập trình viên thì chúng ta cần tối ưu và tự động hóa mọi thứ có thể. Đặc biệt là sau này khi danh sách được bổ sung / thêm bớt thì sao?
Ví dụ đây là một danh sách cơ bản, chỉ gồm chữ:
Còn đây là một danh sách phức tạp hơn một tí, bao gồm ảnh, và chữ, sắp xếp theo từng ô (nếu bạn muốn biết tên app thì nó là MangaRock, app đọc truyện tranh ưa thích của mình):
Các bạn có để ý là, mỗi item trong danh sách ở 2 ảnh ví dụ trên đều na ná nhau không? Đều có cùng kích thước item, khác nội dung mỗi item thôi. Còn đây là ví dụ về một loại danh sách phức tạp hơn nữa, từ app Messenger của Facebook:
Đó, có 2 kiểu bong bóng thoại màu xám và màu xanh dương, căn lề theo 2 bên.
ListView cơ bản nhất
Đúng! Sau đây mình sẽ hướng dẫn các bạn làm một ListView dạng cơ bản nhất.
Tại sao ListView cũng là View mà mình không giới thiệu ở bài trước mà lại đặt ra một bài riêng? Vì cách thực hiện nó khó hơn View bình thường.
Nhưng nếu phân tích ra thì chúng ta sẽ có ListView là:
Một View bình thường. Nó có thể chứa được các View khác (nhưng không phải là ViewGroup) << điểm đặc biệt là đây. Nó cần dữ liệu để hiển thị danh sách ra (mảng, list, array list,…).
Bước 1: Chúng ta lại tạo một project mới, đặt tên là ListViewExample nhé. Với Activity chính là MainActivity:
Bước 2: Ở đây chúng ta sẽ làm một ListView với nội dung hiển thị vô cùng đơn giản: Một mảng các String.
Code thẳng luôn vào MainActivity.java nhé:
package com.howkteam.listviewexample; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String[] items = {"Doan Ngoc Giau", "Pham Kim Long", "Kteam"}; } }
Ok, thế là có mảng rồi, thích nhé. Sang bước tiếp theo nào.
Bước 3: Thêm ListView vào file XML:
Chúng ta xóa bỏ cái TextView đi và thay bằng ListView, nhớ đặt id cho nó:
activity_main.xml
Vậy là xong… chúng ta sang bước… à khoan!
Chưa xong, để hiển thị được mảng String ở trên vào ListView thì chúng ta phải đưa mỗi String vào một View con nằm trong ListView. Mỗi item trong ListView đều có một layout riêng. Các bạn chuột phải vào res/layout > New Android resource file như hình:
Đặt tên cho nó là item_name nhé (mỗi String là tên người mà, để “name” cho dễ hiểu):
Nội dung của file như sau:
item_name.xml
Bước 4: Phần này quan trọng đây! Chúng ta sẽ tạo ra Adapter.
Hỏi: Ớ ớ, Adapter là cái gì? Trả lời: Adapter là class để ánh xạ item view của bạn và item trong danh sách String đầu vào. Trong trường hợp này, nó ánh xạ mỗi phần tử trong mảng String[] items vừa khai báo ở trên.
Nếu các bạn vẫn chưa hiểu thì cứ làm tiếp, bắt chước y như mình, code tiếp, sau đó mình sẽ giải thích bổ sung. Trước đây mình cũng rất mù mờ về khái niệm adapter, sau khi code thì vỡ lẽ ra hết.
Chúng ta tạo một class mới có tên là DataAdapter và cho nó extends từ BaseAdapter:
package com.howkteam.listviewexample; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; public class DataAdapter extends BaseAdapter { @Override public int getCount() { return 0; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(int i, View view, ViewGroup viewGroup) { return null; } }
Các bạn thấy có lỗi đúng không? Không sao, là tại chúng ta chưa viết các method cần implement thôi. Vào menu Code > Implement Methods… (nhớ đặt chuột trong khối lệnh của class DataAdapter):
Hoặc một cách khác là đặt con trỏ chuột giữa dòng báo lỗi và nhấn Alt+Enter > Implement Methods:
Cửa sổ Select Methods to implement hiện ra, chọn tất cả 4 method và nhấn OK:
Và chúng ta có class khung sơ bộ như sau:
package com.howkteam.listviewexample; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; public class DataAdapter extends BaseAdapter { @Override public int getCount() { return 0; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(int i, View view, ViewGroup viewGroup) { return null; } }
Bước 5: Để có thể sử dụng Adapter thì chúng ta cần truyền cho class này dữ liệu dạng danh sách hoặc mảng (ở đây chúng ta dùng mảng, để ý cái String[] items ở bước trước), và truyền qua constructor của nó:
private String[] items; public DataAdapter(String[] items) { this.items = items; }
Tiếp theo, ở hàm getCount(), hàm này sẽ trả về số lượng phần tử hiển thị trong danh sách. Con số này bắt buộc phải nhỏ hơn hoặc bằng số lượng phần tử trong mảng đầu vào, nếu không sẽ bị lỗi IndexOutOfBoundException:
@Override public int getCount() { return items.length; }
Code đầy đủ của cả class DataAdapter.java:
package com.howkteam.listviewexample; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class DataAdapter extends BaseAdapter { private Activity activity; private String[] items; public DataAdapter(Activity activity, String[] items) { this.activity = activity; this.items = items; } @Override public int getCount() { return items.length; } @Override public Object getItem(int i) { return items[i]; } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { LayoutInflater inflater = activity.getLayoutInflater(); view = inflater.inflate(R.layout.item_name, null); TextView tvName = (TextView) view.findViewById(R.id.tv_name); tvName.setText(items[i]); return view; } }
Và cuối cùng cài đặt adapter cho ListView tại MainActivity.java:
package com.howkteam.listviewexample; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.ListView; public class MainActivity extends AppCompatActivity { private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String[] items = {"Doan Ngoc Giau", "Pham Kim Long", "Kteam"}; listView = (ListView) findViewById(R.id.list_view); DataAdapter adapter = new DataAdapter(this, items); listView.setAdapter(adapter); } }
Và chúng ta được như sau:
Ok! tạm thời là như vậy, bài viết này sẽ tạm dừng tại đây với các kiến thức cơ bản nhất về ListView. Chúng ta có một số lưu ý như sau:
ListView cũng chỉ là một View bình thường. Để hiển thị danh sách các phần tử, ListView cần một mảng hoặc một danh sách các dữ liệu đầu vào (model chẳng hạn). Chúng ta không truyền thẳng mảng hay list cho ListView mà cần truyền qua Adapter. Adapter là cầu nối giữa dữ liệu và ListView.
Kết luận
Qua bài này chúng ta đã nắm được ListView là gì, chúng ta phải làm gì để ListView có thể hiển thị danh sách các String đơn giản.
Bài sau chúng ta sẽ quay lại tìm hiểu thêm một chút về ListView, và RecyclerView - một loại View chứa danh sách khác, họ hàng với ListView nhưng tốt hơn, dễ tùy biến hơn rất nhiều. Bên cạnh đó là cơ chế ViewHolder áp dụng được cho cả ListView và RecyclerView nhằm tăng tốc độ khi sử dụng danh sách.
Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập - Thử thách - Không ngại khó”.
Thảo luận
Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần BÌNH LUẬN bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.