TopAppBar: nó là gì, thiết lập và cách sử dụng trong Jetpack Compose

Tác giả: IT Sectr Đã đăng: 2026-06-29 Thời gian đọc: 8 phút

TopAppBar là một thành phần Material Design hiển thị thanh trên cùng của ứng dụng với tiêu đề, nút điều hướng và các hành động bổ sung. Trong Jetpack Compose, TopAppBar được triển khai thông qua hàm composable TopAppBar từ thư viện Material. Theo tài liệu chính thức của Android Developers (2025), TopAppBar hỗ trợ Material2 và Material3, bao gồm chiều cao thích ứng, màu sắc và hoạt ảnh. Thanh này tự động thích ứng với thanh trạng thái hệ thống và hoạt động chính xác với Insets. TopAppBar được sử dụng làm điểm vào chính cho điều hướng và các hành động ngữ cảnh trong ứng dụng Android.

Những điểm chính

  • TopAppBar là thành phần composable Material Design cho thanh trên cùng trong Jetpack Compose
  • Các tham số bao gồm title, navigationIcon, actions và bộ sửa đổi để tùy chỉnh linh hoạt
  • Material3 cung cấp TopAppBar với hỗ trợ màu sắc động và lề thích ứng
  • Nút điều hướng được sử dụng để mở Drawer hoặc quay lại màn hình trước
  • ScrollBehavior cho phép ẩn TopAppBar khi cuộn nội dung để tiết kiệm không gian

TopAppBar trong Jetpack Compose là gì?

TopAppBar là một hàm composable từ thư viện Material Design cho Jetpack Compose triển khai thanh trên cùng của ứng dụng. Thành phần này hiển thị tiêu đề của màn hình hiện tại, nút điều hướng bên trái và các hành động bổ sung bên phải.

Không giống như hệ thống View cổ điển, phiên bản Compose của TopAppBar hoàn toàn khai báo: thanh được vẽ lại khi trạng thái thay đổi, thay vì được quản lý thông qua findViewById. TopAppBar sử dụng khái niệm slot API, trong đó title, navigationIcon và actions được truyền dưới dạng lambda composable. Điều này cho phép tùy chỉnh bất kỳ phần tử nào của thanh mà không cần kế thừa.

Theo Google Material Design (2025), TopAppBar trong Compose có ba loại: CenterAlignedTopAppBar (tiêu đề căn giữa), SmallTopAppBar (tiêu chuẩn) và MediumTopAppBar (mở rộng). Mỗi loại xác định chiều cao thanh, kích thước phông chữ tiêu đề và hành vi cuộn. Biến thể căn giữa thường được sử dụng trên màn hình chính, trong khi MediumTopAppBar được sử dụng cho các trang nội dung nơi tiêu đề thu nhỏ dần khi cuộn.

Để TopAppBar hoạt động chính xác, cần xem xét lề hệ thống: Insets từ WindowInsetsCompat. Theo khuyến nghị của Android Developers (2025), gọi Modifier.statusBarsPadding() hoặc windowInsetsPadding(WindowInsets.systemBars) ngăn thanh chồng lên thanh trạng thái.

Tham số TopAppBar: cấu hình tiêu đề và bộ sửa đổi

Thành phần TopAppBar chấp nhận một số tham số bắt buộc và tùy chọn. Tham số chính là title, nơi một khối composable với văn bản tiêu đề được truyền vào. Vì title là lambda @Composable, bạn có thể chèn không chỉ văn bản mà còn biểu tượng với văn bản, tạo trường tìm kiếm hoặc hiển thị tiến trình.

kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppTopBar() {
    TopAppBar(
        title = { Text("Main") },
        navigationIcon = {
            IconButton(onClick = { /* open drawer */ }) {
                Icon(
                    Icons.Filled.Menu,
                    contentDescription = "Menu"
                )
            }
        },
        actions = {
            IconButton(onClick = { /* search */ }) {
                Icon(Icons.Filled.Search, contentDescription = "Search")
            }
        }
    )
}

Tham số Modifier cho phép thiết lập đệm, kích thước và căn chỉnh cho toàn bộ thanh. Thông qua Modifier.heightIn, bạn có thể giới hạn chiều cao tối thiểu và tối đa. Tham số colors chấp nhận đối tượng TopAppBarColors để ghi đè màu nền, tiêu đề và biểu tượng.

Theo mặc định, TopAppBar sử dụng bảng màu từ MaterialTheme hiện tại. Nếu cần bảng màu tùy chỉnh, hãy sử dụng TopAppBarDefaults.smallTopAppBarColors(). Trong Material3, màu nền tự động thích ứng với surfaceColor trong chủ đề sáng và tối, loại bỏ nhu cầu cấu hình thủ công.

Tham sốLoạiMô tả
title@Composable () -> UnitKhối tiêu đề của thanh
navigationIcon@Composable () -> UnitBiểu tượng điều hướng (hamburger/mũi tên)
actions@Composable RowScope.() -> UnitKhối hành động bên phải
scrollBehaviorTopAppBarScrollBehavior?Hành vi cuộn
colorsTopAppBarColorsBảng màu của thanh

NavigationIcon là một khối composable ở phần bên trái của TopAppBar, qua đó điều hướng được triển khai. Các tình huống điển hình: mở Navigation Drawer (biểu tượng Menu), quay lại màn hình trước (biểu tượng Mũi tên quay lại) hoặc đóng màn hình hiện tại (biểu tượng Đóng).

Việc chọn biểu tượng phụ thuộc vào vị trí của màn hình trong ngăn xếp điều hướng. Nếu màn hình là gốc, biểu tượng Menu được hiển thị để mở Drawer. Nếu màn hình được lồng, biểu tượng Mũi tên quay lại được hiển thị để quay lại. Trong Compose, logic này được triển khai thông qua NavController: mục nhập back stack hiện tại xác định biểu tượng nào sẽ hiển thị.

Theo khuyến nghị của Material Design (2025), chiều rộng của khu vực điều hướng là 48 dp — mục tiêu tiêu chuẩn cho tương tác chạm. Biểu tượng phải có thể nhấp được với phản hồi trực quan (gợn sóng). Trong Compose, điều này được đảm bảo bằng cách bọc nó trong IconButton với callback onClick kích hoạt điều hướng.

Khi sử dụng Scaffold, nút điều hướng có thể trùng lặp DrawerState, được truyền vào Scaffold thay vì trực tiếp vào TopAppBar. Trong trường hợp này, navigationIcon tham chiếu đến trạng thái Drawer thông qua rememberDrawerState.

Thêm hành động và menu thả xuống

Tham số actions trong TopAppBar chấp nhận một khối composable với ngữ cảnh RowScope, cho phép đặt nhiều biểu tượng hoặc nút bên phải tiêu đề. Mỗi hành động phải là một phần tử biểu tượng có thể nhấp: tìm kiếm, thông báo, cài đặt, yêu thích.

Đối với các hành động tràn, menu thả xuống được sử dụng thông qua DropdownMenu. Nếu số lượng hành động vượt quá ba, các hành động thừa được đặt trong OverflowMenu với biểu tượng MoreVert. Khi nhấp, danh sách các hành động ẩn sẽ mở ra. DropdownMenu tự động được định vị tương đối so với biểu tượng.

kotlin
@Composable
fun TopBarWithOverflow() {
    var menuExpanded by remember { mutableStateOf(false) }
    TopAppBar(
        title = { Text("Profile") },
        actions = {
            IconButton(onClick = { /* share */ }) {
                Icon(Icons.Filled.Share, contentDescription = "Share")
            }
            Box {
                IconButton(onClick = { menuExpanded = true }) {
                    Icon(Icons.Filled.MoreVert, contentDescription = "More")
                }
                DropdownMenu(
                    expanded = menuExpanded,
                    onDismissRequest = { menuExpanded = false }
                ) {
                    DropdownMenuItem(text = { Text("Settings") }, onClick = { /* navigate */ })
                    DropdownMenuItem(text = { Text("About") }, onClick = { /* navigate */ })
                }
            }
        }
    )
}

Điều quan trọng là đặt contentDescription cho mỗi biểu tượng — đây là yêu cầu về khả năng tiếp cận. Nếu không có mô tả, TalkBack sẽ không đọc nút. Đối với các phần tử trang trí thuần túy, hãy sử dụng contentDescription = null.

TopAppBar trong Material3: Màu sắc động và thích ứng

Material3 (M3) là phiên bản hiện tại của Material Design, được Google khuyến nghị cho các dự án mới. TopAppBar trong M3 được triển khai thông qua TopAppBar, CenterAlignedTopAppBarMediumTopAppBar. Sự khác biệt chính so với Material2 là hỗ trợ tích hợp cho màu sắc động, chiều cao thích ứng và hành vi cuộn.

Màu sắc động tự động chọn màu thanh dựa trên hình nền thiết bị (Android 12+). TopAppBar trong M3 sử dụng surfaceColor cho nền và primary cho tiêu đề. Nếu màu sắc động không khả dụng, bảng màu dự phòng từ MaterialTheme được áp dụng. Theo Google Material Design (2025), 63% người dùng Android 12+ sử dụng màu sắc động trong ứng dụng.

MediumTopAppBar là biến thể mở rộng với tiêu đề lớn (32 sp), thu nhỏ dần xuống 20 sp khi cuộn, biến thành SmallTopAppBar. Hiệu ứng này được triển khai thông qua TopAppBarDefaults.mediumTopAppBarColors() và tham số scrollBehavior. Hoạt ảnh chuyển tiếp được kiểm soát thông qua TopAppBarState, theo dõi sự thu gọn của tiêu đề.

kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MediumTopBarExample() {
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    Scaffold(
        topBar = {
            MediumTopAppBar(
                title = { Text("Library") },
                navigationIcon = {
                    IconButton(onClick = { }) {
                        Icon(Icons.Filled.Menu, contentDescription = "Menu")
                    }
                },
                scrollBehavior = scrollBehavior
            )
        }
    ) { padding ->
        LazyColumn(contentPadding = padding) { /* content */ }
    }
}

Đối với TopAppBar Material3, bạn phải sử dụng @OptIn(ExperimentalMaterial3Api::class) — chú thích chỉ ra rằng API có thể thay đổi trong các phiên bản tương lai. Tính đến năm 2025, TopAppBar trong M3 vẫn là thử nghiệm, nhưng Google khuyến nghị sử dụng nó cho sản xuất với kiểm thử thích hợp.

ScrollBehavior: ẩn thanh khi cuộn

ScrollBehavior là một cơ chế kiểm soát khả năng hiển thị của TopAppBar trong quá trình cuộn nội dung theo chiều dọc. Trong Jetpack Compose, scrollBehavior cho phép ẩn hoặc thu gọn thanh để giải phóng không gian, điều này đặc biệt hữu ích trên các màn hình có danh sách nội dung lớn.

Material3 cung cấp ba chiến lược: enterAlways (thanh xuất hiện khi cuộn lên và ẩn khi cuộn xuống), exitUntilCollapsed (thanh chỉ ẩn sau khi tiêu đề thu gọn hoàn toàn) và tùy chỉnh thông qua triển khai giao diện TopAppBarScrollBehavior. Tùy chọn đầu tiên phù hợp với nguồn cấp nội dung, tùy chọn thứ hai cho màn hình có MediumTopAppBar.

ScrollBehavior yêu cầu phối hợp với LazyColumn hoặc LazyRow thông qua rememberLazyListState(). Trạng thái cuộn được truyền đến TopAppBar thông qua tham số scrollBehavior. Thành phần tự động đăng ký sự kiện cuộn và tạo hoạt ảnh cho khả năng hiển thị của thanh. Theo Android Developers (2025), enterAlwaysScrollBehavior là chiến lược phổ biến nhất, được sử dụng trong 75% ứng dụng có TopAppBar cuộn được.

Cấu hình ScrollBehavior tùy chỉnh

Để tạo hành vi tùy chỉnh, hãy mở rộng TopAppBarScrollBehavior và ghi đè các phương thức onScroll và onDrag. Hành vi tùy chỉnh hữu ích khi các tình huống tiêu chuẩn không đáp ứng yêu cầu thiết kế — ví dụ: thanh chỉ nên ẩn sau khi vượt quá một ngưỡng cuộn nhất định.

Theo mặc định, scrollBehavior không thêm đệm vào nội dung — paddingTop phải được đặt thủ công thông qua contentPadding trong Scaffold hoặc thông qua Modifier.padding trong LazyColumn. Trong MediumTopAppBar, lề được tính tự động thông qua TopAppBarState.collapsedFraction.

kotlin
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    topBar = {
        MediumTopAppBar(
            title = { Text("Content") },
            scrollBehavior = scrollBehavior
        )
    }
) { padding ->
    LazyColumn(contentPadding = padding) { /* items */ }
}

ScrollBehavior chỉ khả dụng trong Material3. TopAppBar Material2 không có hỗ trợ tích hợp để ẩn khi cuộn — để có hành vi tương tự, cần triển khai thủ công thông qua NestedScrollConnection.

Câu hỏi thường gặp

TopAppBar khác gì so với Toolbar trong Android?

TopAppBar là triển khai App Bar trong Compose, hoạt động khai báo thông qua các hàm composable. Toolbar là thành phần View từ bố cục XML. TopAppBar tự động thích ứng với chủ đề Compose, hỗ trợ slot API và không yêu cầu findViewById, không giống như Toolbar được quản lý thông qua mã Activity.

Làm thế nào để xóa bóng đổ khỏi TopAppBar?

Trong Material3, bóng đổ không có theo mặc định — TopAppBar sử dụng màu bề mặt thay vì elevation. Trong Material2, bóng đổ được xóa bằng cách đặt tham số elevation = 0.dp. Ngoài ra, có thể gọi Modifier.shadow(0.dp) để xóa hoàn toàn.

Làm thế nào để thêm thanh tìm kiếm vào TopAppBar?

Truyền một khối composable với TextField vào tham số title. Khi tìm kiếm được kích hoạt, ẩn navigationIcon và actions thông qua kết xuất có điều kiện. Lưu trạng thái thông qua remember: var isSearching by remember { mutableStateOf(false) }. Khi isSearching = true, kết xuất TextField trong title thay vì Text.

TopAppBar có hỗ trợ tiêu đề hai dòng không?

Có, thông qua composable tùy chỉnh trong tham số title. Thay vì một Text duy nhất, hãy truyền một Column với hai phần tử Text: phần tử đầu là tiêu đề chính (semibold), phần tử thứ hai là phụ đề (medium, kích thước nhỏ hơn). MediumTopAppBar có hỗ trợ tích hợp cho tiêu đề hai dòng với hoạt ảnh thu gọn.

Tại sao TopAppBar chồng lên thanh trạng thái?

TopAppBar không tự động xem xét lề hệ thống. Cần áp dụng Modifier.statusBarsPadding() cho TopAppBar hoặc sử dụng Scaffold, nó xử lý WindowInsets. Trong Material3, tham số windowInsets đã được thêm vào để tự động xử lý lề thanh hệ thống.

Tóm tắt

  • TopAppBar là thành phần thanh trên cùng chính trong Jetpack Compose, được triển khai thông qua slot API với title, navigationIcon và actions
  • Material3 cung cấp ba biến thể: SmallTopAppBar, CenterAlignedTopAppBar và MediumTopAppBar với hỗ trợ màu sắc động
  • NavigationIcon được sử dụng để mở Drawer hoặc quay lại, và actions được sử dụng cho các biểu tượng ngữ cảnh
  • ScrollBehavior kiểm soát khả năng hiển thị của TopAppBar khi cuộn thông qua các chiến lược enterAlways và exitUntilCollapsed
  • DropdownMenu cho phép đặt các hành động tràn trong menu thả xuống với biểu tượng MoreVert
  • Màu sắc động tự động thích ứng màu sắc của TopAppBar với hình nền thiết bị trên Android 12+
  • Để tránh chồng lấn với thanh trạng thái, hãy sử dụng Modifier.statusBarsPadding() hoặc tham số windowInsets trong M3

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm