Flutter: Hướng dẫn xây dựng bổ cục trong Flutter
Những gì bạn sẽ học:
- Cơ chế bố cục của Flutter hoạt động như thế nào.
- Cách sắp xếp các widget theo chiều dọc và chiều ngang.
- Cách xây dựng bố cục trong Flutter.
Đây là hướng dẫn xây dựng bố cục trong Flutter. Bạn sẽ xây dựng bố cục cho ứng dụng sau:
Ứng dụng đã hoàn thành
Bài hướng dẫn này sẽ giải thích cách tiếp cận bố cục của Flutter và chỉ ra cách đặt một tiện ích con trên màn hình. Sau khi thảo luận về cách sắp xếp các widget theo chiều ngang và chiều dọc, một số widget bố cục phổ biến nhất sẽ được đề cập.
Nếu bạn muốn hiểu "một bức tranh lớn" về cơ chế bố cục, hãy bắt đầu với cách tiếp cận bố cục của Flutter.
Bước 0: Tạo mã cơ sở ứng dụng
Đảm bảo thiết lập môi trường của bạn, sau đó thực hiện như sau:
- Tạo ứng dụng Flutter “Hello World” cơ bản.
- Thay đổi tiêu đề thanh ứng dụng và tiêu đề ứng dụng như sau:
lib/main.dart
@override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', title: 'Flutter layout demo', home: Scaffold( appBar: AppBar( title: Text('Welcome to Flutter'), title: Text('Flutter layout demo'), ), body: Center( child: Text('Hello World'),
Bước 1: Sơ đồ bố cục
Bước đầu tiên là chia nhỏ bố cục thành các yếu tố cơ bản của nó:
- Xác định các hàng và cột.
- Bố cục có bao gồm lưới không?
- Có các yếu tố trùng lặp không?
- Giao diện người dùng có cần tab không?
- Lưu ý các khu vực yêu cầu căn chỉnh, đệm hoặc đường viền.
Đầu tiên, xác định các phần tử lớn hơn. Trong ví dụ này, bốn phần tử được sắp xếp thành một cột: một hình ảnh, hai hàng và một khối văn bản.
Phần tử cột (khoanh đỏ)
Tiếp theo, lập sơ đồ từng hàng. Hàng đầu tiên, được gọi là phần Tiêu đề, có 3 con: một cột văn bản, một biểu tượng ngôi sao và một số. Con đầu tiên của nó, cột, chứa 2 dòng văn bản. Cột đầu tiên đó chiếm nhiều dung lượng, vì vậy nó phải được bao bọc trong widget Expanded.
Khi bố cục đã được lập sơ đồ, cách dễ dàng nhất để thực hiện là tiếp cận từ dưới lên để triển khai nó. Để giảm thiểu sự nhầm lẫn trực quan của mã bố cục lồng nhau sâu, hãy đặt một số triển khai trong các biến và hàm.
Bước 2: Triển khai hàng tiêu đề
Đầu tiên, bạn sẽ xây dựng cột bên trái trong phần tiêu đề. Thêm mã sau vào đầu phương thức build()
của lớp MyApp
:
Widget titleSection = Container( padding: const EdgeInsets.all(32), child: Row( children: [ Expanded( /*1*/ child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /*2*/ Container( padding: const EdgeInsets.only(bottom: 8), child: Text( 'Oeschinen Lake Campground', style: TextStyle( fontWeight: FontWeight.bold, ), ), ), Text( 'Kandersteg, Switzerland', style: TextStyle( color: Colors.grey[500], ), ), ], ), ), /*3*/ Icon( Icons.star, color: Colors.red[500], ), Text('41'), ], ), );
/*1*/ Đặt một widget Column
bên trong widget Expanded
để sử dụng tất cả không gian trống còn lại trong hàng. Đặt thuộc tính crossAxisAlignment
thành CrossAxisAlignment.start
để xác định vị trí cột ở đầu hàng.
/*2*/ Đặt hàng văn bản đầu tiên bên trong một Container
để cho phép bạn thêm phần đệm. Con thứ hai trong Column
, cũng là văn bản để hiển thị là màu xám.
/*3*/ Hai mục cuối cùng trong hàng tiêu đề là biểu tượng ngôi sao, sơn màu đỏ và văn bản "41". Toàn bộ hàng nằm trong một Container
và được đệm dọc theo mỗi cạnh 32 pixel. Thêm phần tiêu đề vào nội dung ứng dụng như sau:
File /lib/main.dart:
return MaterialApp( title: 'Flutter layout demo', home: Scaffold( appBar: AppBar( title: Text('Flutter layout demo'), ), body: Center( child: Text('Hello World'), body: Column( children: [ titleSection, ], ), ), );
Mẹo:
- Khi dán mã vào ứng dụng của bạn, thụt lề có thể bị lệch. Bạn có thể sửa lỗi này trong trình chỉnh sửa Flutter của mình bằng cách sử dụng hỗ trợ định dạng lại tự động.
- Để có trải nghiệm phát triển nhanh hơn, hãy thử tính năng tải lại nóng của Flutter.
- Nếu bạn gặp sự cố, hãy so sánh mã của bạn với lib/main.dart.
Bước 3: Triển khai hàng nút
Phần nút chứa 3 cột sử dụng cùng một bố cục - một biểu tượng trên một hàng văn bản. Các cột trong hàng này cách đều nhau, văn bản và biểu tượng được sơn bằng màu chính.
Vì mã để xây dựng mỗi cột gần như giống nhau, bạn hãy tạo một phương thức trợ giúp riêng có tên buildButtonColumn()
, phương thức này nhận một màu, một Icon
và Text
và trả về một cột với các widget con của nó được thể hiện bằng màu đã cho.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { // ··· } Column _buildButtonColumn(Color color, IconData icon, String label) { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: color), Container( margin: const EdgeInsets.only(top: 8), child: Text( label, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w400, color: color, ), ), ), ], ); } }
Hàm sẽ có nhiệm vụ thêm biểu tượng trực tiếp vào cột. Văn bản nằm trong Container
với lề chỉ trên cùng, ngăn cách văn bản với biểu tượng.
Xây dựng hàng chứa các cột này bằng cách gọi hàm và chuyển màu Icon
, và văn bản cụ thể cho cột đó. Căn chỉnh các cột dọc theo trục chính bằng cách sử dụng MainAxisAlignment.spaceEvenly
để sắp xếp không gian trống đồng đều trước, giữa và sau mỗi cột. Thêm mã sau ngay bên dưới khai báo titleSection
bên trong phương thức build()
:
Color color = Theme.of(context).primaryColor; Widget buttonSection = Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildButtonColumn(color, Icons.call, 'CALL'), _buildButtonColumn(color, Icons.near_me, 'ROUTE'), _buildButtonColumn(color, Icons.share, 'SHARE'), ], ), );
Thêm phần nút vào nội dung:
Bước 4: Triển khai phần văn bản
Xác định phần văn bản dưới dạng một biến. Đặt văn bản trong một Container
và thêm phần đệm dọc theo mỗi cạnh. Thêm mã sau ngay bên dưới khai báo buttonSection
:
Widget textSection = Container( padding: const EdgeInsets.all(32), child: Text( 'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese ' 'Alps. Situated 1,578 meters above sea level, it is one of the ' 'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a ' 'half-hour walk through pastures and pine forest, leads you to the ' 'lake, which warms to 20 degrees Celsius in the summer. Activities ' 'enjoyed here include rowing, and riding the summer toboggan run.', softWrap: true, ), );
Bằng cách đặt softwrap
thành true, các dòng văn bản sẽ lấp đầy chiều rộng cột trước khi bao quanh một ranh giới từ.
Thêm phần văn bản vào nội dung:
Bước 5: Thực hiện phần hình ảnh
Ba trong bốn phần tử cột hiện đã hoàn thành, chỉ còn lại hình ảnh. Thêm tệp hình ảnh vào ví dụ:
- Tạo một thư mục
images
ở đầu dự án. - Thêm ảnh lake.jpg.
Lưu ý rằng
wget
không hoạt động để lưu tệp nhị phân này. Hình ảnh gốc có sẵn trực tuyến theo giấy phép Creative Commons, nhưng nó lớn và tải chậm.
- Cập nhật file
pubspec.yaml
để bao gồm một thẻassets
thẻ. Điều này làm cho hình ảnh có sẵn cho mã của bạn:
/pubspec.yamlflutter: uses-material-design: true assets: images/lake.jpg
Mẹo:
- Lưu ý là
pubspec.yaml
phân biệt chữ hoa và chữ thường nên cần viết làassets:
và thể hiện URL hình ảnh phải như hình trên.- Tệp pubspec cũng nhạy cảm với khoảng trắng, vì vậy hãy sử dụng thụt lề thích hợp.
Bây giờ bạn có thể tham khảo hình ảnh từ đoạn mã của mình:
BoxFit.cover
cho framework biết rằng hình ảnh phải càng nhỏ càng tốt nhưng vẫn bao phủ toàn bộ hộp kết xuất của nó.
Bước 6: Lần chạm cuối cùng
Trong bước cuối cùng này, hãy sắp xếp tất cả các phần tử trong một ListView
, thay vì một Column
, bởi vì ListView
hỗ trợ ứng dụng cuộn nội dung khi ứng dụng được chạy trên một thiết bị nhỏ.
Code Dart: main.dart
Ảnh: images
Pubspec: pubspec.yaml
Đó là nó! Khi bạn tải lại nóng ứng dụng, bạn sẽ thấy bố cục ứng dụng giống như ảnh chụp màn hình ở đầu bài viết này.
Bạn có thể thêm tương tác vào bố cục này bằng cách xem bài viết Thêm tương tác vào ứng dụng Flutter của bạn.