Scroll là một hành vi cơ bản và thiết yếu trong hầu hết mọi ứng dụng di động. Flutter cung cấp nhiều widget để bạn có thể thêm khả năng scroll vào giao diện người dùng của mình. Hôm nay chúng ta sẽ tập trung vào SingleChildScrollView
cho các nội dung đơn giản, NestedScrollView
cho các tình huống scroll phức tạp lồng nhau, và giới thiệu sơ lược về CustomScrollView
cho các hiệu ứng tùy chỉnh nâng cao.
Mục tiêu bài học
- Hiểu rõ mục đích và trường hợp sử dụng của
SingleChildScrollView
. - Nắm vững cách sử dụng
NestedScrollView
để tạo hiệu ứng scroll lồng nhau mượt mà. - Phân biệt khi nào nên dùng
SingleChildScrollView
vàNestedScrollView
. - Làm quen với khái niệm và mục đích của
CustomScrollView
trong việc tạo hiệu ứng scroll tùy chỉnh.
Các widget scroll cơ bản và nâng cao
1. SingleChildScrollView
-
Mục đích: Cho phép một widget con duy nhất có thể scroll được khi nội dung của nó vượt quá kích thước của vùng chứa cha.
-
Trường hợp sử dụng: Thích hợp cho các trang hoặc phần nội dung không quá dài và không yêu cầu hiệu ứng scroll phức tạp, ví dụ như một form đăng ký đơn giản hoặc một trang giới thiệu ngắn.
-
Ví dụ:
SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Tiêu đề trang', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), SizedBox(height: 16), Text('Nội dung bài viết', style: TextStyle(fontSize: 16)), SizedBox(height: 24), TextField(decoration: InputDecoration(labelText: 'Tên')), TextField(decoration: InputDecoration(labelText: 'Email')), ElevatedButton(onPressed: () {}, child: Text('Gửi')), SizedBox(height: 50), ], ), ), )
2. NestedScrollView
-
Mục đích: Quản lý các tình huống scroll lồng nhau, cho phép nhiều vùng có khả năng scroll phối hợp scroll một cách mượt mà.
-
Trường hợp sử dụng: Khi bạn có cấu trúc giao diện phức tạp hơn, đặc biệt là khi:
- Bạn muốn có một
AppBar
có hiệu ứng scroll thu gọn (SliverAppBar
vớiflexibleSpace
). - Bạn có một thanh điều hướng cố định (ví dụ:
TabBar
vớipinned: true
) nằm bên dướiAppBar
. - Các vùng nội dung bên dưới thanh điều hướng cũng cần có khả năng scroll độc lập (ví dụ: các
ListView
hoặcGridView
bên trong các tab củaTabBarView
).
- Bạn muốn có một
-
Ví dụ (cấu trúc cơ bản với
ListView
trongTabBarView
):NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ SliverAppBar( title: Text('Tiêu đề'), expandedHeight: 200, floating: false, pinned: true, flexibleSpace: FlexibleSpaceBar( background: Image.network('[https://picsum.photos/400](https://picsum.photos/400)', fit: BoxFit.cover), ), bottom: TabBar( tabs: [ Tab(text: "Tab 1"), Tab(text: "Tab 2"), ], ), ), ], body: TabBarView( children: [ ListView.builder( itemCount: 30, itemBuilder: (context, index) => ListTile(title: Text('Item $index')), ), Center(child: Text('Nội dung tab 2')), ], ), )
3. CustomScrollView
(Giới thiệu)
-
Mục đích: Cung cấp khả năng xây dựng các hiệu ứng scroll tùy chỉnh phức tạp bằng cách kết hợp các
Sliver
widgets. -
Trường hợp sử dụng: Khi bạn cần kiểm soát hoàn toàn cách các phần của giao diện phản ứng với hành vi scroll, chẳng hạn như tạo hiệu ứng paralax, ẩn hiện các phần tử dựa trên vị trí scroll, hoặc tích hợp các hiệu ứng scroll độc đáo khác.
-
Khái niệm:
CustomScrollView
nhận một danh sách cácSliver
widgets trong thuộc tínhslivers
. Các sliver này mô tả các phần có thể cuộn của giao diện và cách chúng tương tác với hành vi scroll chung. -
Ví dụ (cấu trúc cơ bản):
CustomScrollView( slivers: [ SliverAppBar( expandedHeight: 150, pinned: true, flexibleSpace: FlexibleSpaceBar(title: Text('Custom Scroll')), ), SliverList(delegate: SliverChildBuilderDelegate( (context, index) => ListTile(title: Text('Item $index')), childCount: 20, )), SliverFillRemaining( child: Center(child: Text('Phần còn lại')), ), ], )
Lựa chọn Widget scroll phù hợp
- Nội dung đơn giản, không quá dài:
SingleChildScrollView
. - Giao diện có
AppBar
phức tạp (thu gọn) và/hoặcTabBar
với nội dung cuộn độc lập:NestedScrollView
. - Yêu cầu hiệu ứng scroll tùy chỉnh và kiểm soát chi tiết:
CustomScrollView
kết hợp với cácSliver
widgets.
Các lỗi thường gặp khi làm việc với scroll:
- Scroll không hoạt động:** Đảm bảo widget scroll có kích thước xác định hoặc được đặt trong một ngữ cảnh cho phép nó xác định kích thước (ví dụ: trong
Expanded
choSingleChildScrollView
khi nằm trongColumn
hoặcRow
không có kích thước cố định). - Scroll chồng chéo:** Tránh lồng các widget scroll trực tiếp mà không có biện pháp quản lý kích thước.
NestedScrollView
được thiết kế để giải quyết vấn đề này trong các tình huống phức tạp. - Hiệu suất (đặc biệt với
SingleChildScrollView
và nội dung rất dài):SingleChildScrollView
tải toàn bộ nội dung cùng một lúc, vì vậy không phù hợp với nội dung quá dài. Trong trường hợp đó, hãy xem xétListView
hoặcCustomScrollView
với các slivers tải nội dung một cách lười biếng.
Kết luận:
Trong bài học này, chúng ta đã tập trung vào SingleChildScrollView
cho các trường hợp scroll đơn giản, NestedScrollView
cho việc quản lý scroll lồng nhau phức tạp (thường gặp với AppBar
và TabBar
), và có một cái nhìn tổng quan về CustomScrollView
cho các hiệu ứng scroll tùy chỉnh mạnh mẽ. Việc lựa chọn widget phù hợp sẽ giúp bạn xây dựng các giao diện người dùng mượt mà và đáp ứng tốt trong mọi tình huống.
Ngày mai mình sẽ tiếp tục với một phần vô cùng hay ho – hiển thị danh sách có bố cục đẹp hơn bằng Card
, ListTile
và custom layout
trong danh sách.
Cảm ơn các bạn đã theo dõi.