Trong quá trình phát triển ứng dụng Android, việc hiển thị dữ liệu dạng bảng (table) là một nhu cầu phổ biến, đặc biệt đối với các ứng dụng quản lý, thống kê, hoặc hiển thị danh sách có cấu trúc đa chiều. Tuy Android không cung cấp một widget “Table” mạnh mẽ như trong HTML, nhưng với TableLayout, TableRow, RecyclerView, GridLayout, và các thư viện bên thứ ba, bạn vẫn có thể tạo ra những bảng đẹp mắt, linh hoạt và hiệu năng cao.
Bài viết này sẽ:
Giải thích khái niệm và cách hoạt động của TableLayout và TableRow.
So sánh TableLayout với các giải pháp thay thế (RecyclerView + GridLayoutManager, GridLayout, FlexboxLayout, etc.).
Hướng dẫn chi tiết cách tạo bảng đơn giản, bảng có tiêu đề cố định, bảng cuộn ngang và dọc.
Đưa ra các mẹo tối ưu hoá hiệu suất và UI/UX.
Cung cấp ví dụ thực tế, source code và giải thích từng dòng.
Giới thiệu một số thư viện mở rộng giúp vẽ table nhanh hơn (TableView, Android-TableView, etc.).
Sau khi đọc bài này, bạn sẽ có thể tự tin xây dựng bất kỳ loại bảng nào trong Android, từ bảng tĩnh chỉ hiển thị dữ liệu cho đến bảng động, có pagination, sorting, và filter.
2. Cấu trúc cơ bản của TableLayout
2.1. TableLayout là gì?
TableLayout là một ViewGroup trong Android, cho phép bố trí các thành phần con (thường là TableRow) theo dạng lưới giống như bảng trong HTML. Các đặc điểm chính:
android:stretchColumns="" làm cho các cột tự động mở rộng để lấp đầy chiều rộng còn lại.
Header được tô nền khác để dễ phân biệt.
3.2. Bước 2: Thêm dữ liệu động từ Java/Kotlin
class MainActivity : AppCompatActivity() { private lateinit var tableLayout: TableLayout data class Product(val id: Int, val name: String, val price: String) private val productList = listOf( Product(1, "Bánh mì", "15,000₫"), Product(2, "Cà phê", "20,000₫"), Product(3, "Trà sữa", "30,000₫") ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tableLayout = findViewById(R.id.tableLayout) // Bắt đầu từ index 1 vì row 0 là header for (product in productList) { val row = layoutInflater.inflate(R.layout.table_row_item, null) as TableRow // Đặt dữ liệu (row.getChildAt(0) as TextView).text = product.id.toString() (row.getChildAt(1) as TextView).text = product.name (row.getChildAt(2) as TextView).text = product.price // Thêm vào TableLayout tableLayout.addView(row) } }
}
File table_row_item.xml (được tái sử dụng cho mỗi dòng):
Lưu ý: Khi dữ liệu lớn (hàng > 50), việc sử dụng TableLayout sẽ gây lag vì mỗi hàng là một view riêng. Trong trường hợp này, chúng ta nên chuyển sang RecyclerView.
Cách Vẽ Table Trong Android
Có thể bạn quan tâm: Cách Vẽ Sữa Lên Mặt: Hướng Dẫn Chi Tiết Từ Cơ Bản Đến Nâng Cao
4. Khi nào nên dùng RecyclerView + GridLayoutManager thay vì TableLayout?
Tiêu chí
TableLayout
RecyclerView + GridLayoutManager
Số lượng hàng
< 30 (tĩnh)
> 30, dữ liệu động, pagination
Hiệu năng
Tải toàn bộ view vào bộ nhớ
Reuse view holder, chỉ tạo những hàng hiển thị
Tính năng nâng cao
Giới hạn (sort, filter)
Dễ dàng tích hợp sort, filter, animation
Cuộn ngang + dọc
Cần lồng HorizontalScrollView + ScrollView (khó)
LinearLayoutManager hoặc GridLayoutManager hỗ trợ cả 2 chiều
5.3. Cấu hình RecyclerView trong Activity/Fragment
Cách Vẽ Table Trong Android
Có thể bạn quan tâm: Cách Vẽ Sổ Kế Toán Chuẩn Xác Và Hiệu Quả: Hướng Dẫn Từ A Đến Z
class TableActivity : AppCompatActivity() { private lateinit var rvTable: RecyclerView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_table) rvTable = findViewById(R.id.rvTable) // Dữ liệu mẫu val header = listOf("STT", "Tên", "Giá", "Số lượng") val rows = mutableListOf<List<String>>() for (i in 1..200) { rows.add(listOf(i.toString(), "Sản phẩm $i", "${i 1000}₫", (i % 10 + 1).toString())) } rvTable.layoutManager = LinearLayoutManager(this) // cuộn dọc rvTable.adapter = TableAdapter(header, rows) rvTable.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL)) }
}
5.4. Cuộn ngang (nếu số cột quá nhiều)
Khi số cột lớn, mỗi TableRow có thể vượt chiều rộng màn hình. Ta có thể lồng RecyclerView trong một HorizontalScrollView, hoặc tạo một RecyclerView lồng nhau (nested RecyclerView). Dưới đây là cách nhanh nhất:
val tableView = findViewById<TableView>(R.id.tableView)
val columnHeaderAdapter = MyColumnHeaderAdapter(columnHeaders)
val rowHeaderAdapter = MyRowHeaderAdapter(rowHeaders)
val cellAdapter = MyCellAdapter(cellData) tableView.setAdapter(columnHeaderAdapter, rowHeaderAdapter, cellAdapter)
Thư viện này sử dụng RecyclerView nội bộ, vì thế hiệu năng rất tốt ngay cả với hàng nghìn.
7.2. TableView (github.com/IsmaiL/TableView)
Đặc điểm: Dễ tích hợp, hỗ trợ scroll đồng thời cả chiều dọc và ngang, có thể lock cột/row.
Cần tính năng nâng cao (sticky header, drag‑drop, filter) mà không muốn tự xây dựng.
Bạn chỉ cần lựa chọn giải pháp phù hợp, áp dụng các mẫu code trên, và tùy biến thêm theo yêu cầu dự án. Hy vọng bài viết đã cung cấp đủ kiến thức và công cụ để bạn tự tin vẽ table trong Android một cách hiệu quả, tối ưu và đẹp mắt. Chúc bạn thành công!