Flutter – Giới thiệu về bố cục


Vì khái niệm cốt lõi của Chớp cánhMọi điềuphụ tùng, Chớp cánh kết hợp chức năng bố cục giao diện người dùng vào chính các widget. Chớp cánh cung cấp khá nhiều widget được thiết kế đặc biệt như Vùng chứa, Trung tâm, Căn chỉnh, v.v., chỉ với mục đích tạo ra giao diện người dùng. Các widget xây dựng bằng cách soạn các widget khác thường sử dụng các widget bố cục. Hãy sử dụng tìm hiểu Chớp cánh khái niệm bố cục trong chương này.

Loại tiện ích bố cục

Các widget bố cục có thể được nhóm thành hai danh mục riêng biệt dựa trên con của nó –

  • Widget hỗ trợ một đứa trẻ
  • Widget hỗ trợ nhiều trẻ em

Hãy để chúng tôi tìm hiểu cả loại widget và chức năng của nó trong các phần sắp tới.

Các tiện ích con đơn

Trong danh mục này, các widget sẽ chỉ có một widget là con của nó và mọi widget sẽ có một chức năng bố cục đặc biệt.

Ví dụ, Trung tâm widget chỉ tập trung vào widget con đối với widget cha của nó và Thùng đựng hàng widget cung cấp sự linh hoạt hoàn toàn để đặt nó con ở bất kỳ vị trí nào bên trong nó bằng cách sử dụng các tùy chọn khác nhau như đệm, trang trí, v.v.,

Các tiện ích con đơn lẻ là các tùy chọn tuyệt vời để tạo tiện ích con chất lượng cao có chức năng đơn lẻ như nút, nhãn, v.v.,

Mã để tạo một nút đơn giản bằng cách sử dụng Thùng đựng hàng widget như sau –

class MyButton extends StatelessWidget {
   MyButton({Key key}) : super(key: key); 

   @override 
   Widget build(BuildContext context) {
      return Container(
         decoration: const BoxDecoration(
            border: Border(
               top: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
               left: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
               right: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
               bottom: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
            ),
         ),
         child: Container(
            padding: const
            EdgeInsets.symmetric(horizontal: 20.0, vertical: 2.0),
            decoration: const BoxDecoration(
               border: Border(
                  top: BorderSide(width: 1.0, color: Color(0xFFFFDFDFDF)),
                  left: BorderSide(width: 1.0, color: Color(0xFFFFDFDFDF)),
                  right: BorderSide(width: 1.0, color: Color(0xFFFF7F7F7F)),
                  bottom: BorderSide(width: 1.0, color: Color(0xFFFF7F7F7F)),
               ),
               color: Colors.grey,
            ),
            child: const Text(
               'OK',textAlign: TextAlign.center, style: TextStyle(color: Colors.black)
            ), 
         ), 
      ); 
   }
}

Ở đây, chúng tôi đã sử dụng hai tiện ích con – một Thùng đựng hàng widget và một Chữ tiện ích con. Kết quả của tiện ích là một nút tùy chỉnh như hình dưới đây –

ĐƯỢC RỒI

Hãy để chúng tôi kiểm tra một số tiện ích bố cục con đơn lẻ quan trọng nhất được cung cấp bởi Chớp cánh

  • Đệm lót – Được sử dụng để sắp xếp widget con của nó bằng phần đệm đã cho. Ở đây, đệm có thể được cung cấp bởi EdgeInsets lớp.

  • Căn chỉnh – Căn chỉnh tiện ích con của nó trong chính nó bằng cách sử dụng giá trị của sự liên kết tài sản. Giá trị cho sự liên kết tài sản có thể được cung cấp bởi FractionalOffset lớp. Các FractionalOffset lớp xác định các hiệu số về khoảng cách từ phía trên bên trái.

Một số giá trị có thể có của hiệu số như sau:

  • FractionalOffset (1,0, 0,0) đại diện cho phía trên bên phải.

  • FractionalOffset (0.0, 1.0) đại diện cho phía dưới bên trái.

Một mã mẫu về hiệu số được hiển thị bên dưới:

Center(
   child: Container(
      height: 100.0, 
      width: 100.0, 
      color: Colors.yellow, child: Align(
         alignment: FractionalOffset(0.2, 0.6),
         child: Container( height: 40.0, width:
            40.0, color: Colors.red,
         ), 
      ), 
   ), 
)

Ứng dụng hello world của chúng tôi đang sử dụng các widget bố cục dựa trên vật liệu để thiết kế trang chủ. Hãy để chúng tôi sửa đổi ứng dụng hello world của mình để xây dựng trang chủ bằng cách sử dụng các widget bố cục cơ bản như được chỉ định bên dưới –

  • Thùng đựng hàng – Tiện ích vùng chứa chung, con đơn, dựa trên hộp với căn chỉnh, đệm, đường viền và lề cùng với các tính năng tạo kiểu phong phú.

  • Trung tâm – Đơn giản, một widget vùng chứa con, tập trung vào widget con của nó.

Mã sửa đổi của MyHomePageỨng dụng của tôi widget như bên dưới –

class MyApp extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
      return MyHomePage(title: "Hello World demo app");
   }
}
class MyHomePage extends StatelessWidget {
   MyHomePage({Key key, this.title}) : super(key: key);
   final String title;
   @override
   Widget build(BuildContext context) {
      return Container(
         decoration: BoxDecoration(color: Colors.white,),
         padding: EdgeInsets.all(25), child: Center(
            child:Text(
               'Hello World', style: TextStyle(
                  color: Colors.black, letterSpacing: 0.5, fontSize: 20,
               ),
               textDirection: TextDirection.ltr,
            ),
         )
      );
   }
}

Nơi đây,

  • Thùng đựng hàng widget là cấp cao nhất hoặc widget gốc. Thùng đựng hàng được cấu hình bằng cách sử dụng trang tríđệm lót tài sản để bố trí nội dung của nó.

  • BoxDecoration có nhiều thuộc tính như màu sắc, đường viền, v.v., để trang trí Thùng đựng hàng widget và ở đây, màu sắc được sử dụng để thiết lập màu sắc của vùng chứa.

  • đệm lót sau đó Thùng đựng hàng widget được thiết lập bằng cách sử dụng dgeInsets lớp, cung cấp tùy chọn để chỉ định giá trị đệm.

  • Trung tâm là tiện ích con của Thùng đựng hàng tiện ích con. Lại, Chữ là con của Trung tâm tiện ích con. Chữ được sử dụng để hiển thị thông báo và Trung tâm được sử dụng để căn giữa tin nhắn văn bản đối với tiện ích con, Thùng đựng hàng.

Kết quả cuối cùng của đoạn mã được đưa ra ở trên là một mẫu bố cục như được hiển thị bên dưới:

Kết quả cuối cùng

Nhiều tiện ích con

Trong danh mục này, một widget nhất định sẽ có nhiều hơn một widget con và bố cục của mỗi widget là duy nhất.

Ví dụ, Hàng ngang widget cho phép đẻ ra các con của nó theo hướng ngang, trong khi Cột widget cho phép đẻ ra các con của nó theo hướng thẳng đứng. Bằng cách sáng tác Hàng ngangCộtwidget với bất kỳ mức độ phức tạp nào cũng có thể được xây dựng.

Hãy cùng chúng tôi tìm hiểu một số widget thường dùng trong phần này.

  • Hàng ngang – Cho phép sắp xếp các con của nó theo chiều ngang.

  • Cột – Cho phép sắp xếp các con của nó theo chiều dọc.

  • ListView – Cho phép sắp xếp các con của nó dưới dạng danh sách.

  • Chế độ hiển thị theo ô – Cho phép sắp xếp con cái của nó như một bộ sưu tập.

  • Đã mở rộng – Được sử dụng để làm cho widget con của Row và Column chiếm diện tích tối đa có thể.

  • Bàn – Phụ tùng dựa trên bảng.

  • lưu lượng – Widget dựa trên dòng chảy.

  • Cây rơm – Widget dựa trên ngăn xếp.

Ứng dụng bố cục nâng cao

Trong phần này, chúng ta hãy tìm hiểu cách tạo một giao diện người dùng phức tạp của danh sách sản phẩm với thiết kế tùy chỉnh bằng cách sử dụng cả tiện ích con bố cục đơn và nhiều tiện ích con.

Với mục đích này, hãy làm theo trình tự được đưa ra dưới đây:

  • Tạo một cái mới Chớp cánh ứng dụng trong Android studio, product_layout_app.

  • Thay thế cái main.dart mã với mã sau –

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp()); 

class MyApp extends StatelessWidget {
   // This widget is the root of your application.
   @override 
   Widget build(BuildContext context) {
      return MaterialApp( 
         title: 'Flutter Demo', theme: ThemeData( 
         primarySwatch: Colors.blue,), 
         home: MyHomePage(title: 'Product layout demo home page'),
      ); 
   } 
} 
class MyHomePage extends StatelessWidget {
   MyHomePage({Key key, this.title}) : super(key: key); 
   final String title; 
      
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text(this.title),), 
         body: Center(child: Text( 'Hello World', )), 
      ); 
   }
}
  • Nơi đây,

  • Chúng tôi đã tạo MyHomePage tiện ích con bằng cách mở rộng StatelessWidget thay vì mặc định StatefulWidget và sau đó loại bỏ mã có liên quan.

  • Bây giờ, hãy tạo một tiện ích con mới, Hộp sản phẩm theo thiết kế quy định như hình dưới đây –

Hộp sản phẩm

class ProductBox extends StatelessWidget {
   ProductBox({Key key, this.name, this.description, this.price, this.image}) 
      : super(key: key); 
   final String name; 
   final String description; 
   final int price; 
   final String image; 

   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), height: 120,  child: Card( 
            child: Row(
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[
                  Image.asset("assets/appimages/" +image), Expanded(
                     child: Container(
                        padding: EdgeInsets.all(5), child: Column(
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                              children: <Widget>[ 
                              
                              Text(this.name, style: TextStyle(fontWeight: 
                                 FontWeight.bold)), Text(this.description), 
                              Text("Price: " + this.price.toString()), 
                           ], 
                        )
                     )
                  )
               ]
            )
         )
      );
   }
}
  • Hộp sản phẩm đã sử dụng bốn đối số như được chỉ định bên dưới:

    • name – Tên sản phẩm

    • mô tả – Mô tả sản phẩm

    • price – Giá của sản phẩm

    • hình ảnh – Hình ảnh của sản phẩm

  • Hộp sản phẩm sử dụng bảy tiện ích con tích hợp như được chỉ định bên dưới –

    • Thùng đựng hàng
    • Đã mở rộng
    • Hàng ngang
    • Cột
    • Thẻ
    • Chữ
    • Hình ảnh
  • Hộp sản phẩm được thiết kế bằng cách sử dụng widget được đề cập ở trên. Sự sắp xếp hoặc phân cấp của tiện ích được chỉ định trong sơ đồ hiển thị bên dưới –

Thứ bậc của tiện ích con

assets: 
   - assets/appimages/floppy.png 
   - assets/appimages/iphone.png 
   - assets/appimages/laptop.png 
   - assets/appimages/pendrive.png 
   - assets/appimages/pixel.png 
   - assets/appimages/tablet.png

điện thoại Iphone

iPhone.png

Pixel

Pixel.png

Máy tính xách tay

Laptop.png

Máy tính bảng

Tablet.png

Pendrive

Pendrive.png

Đĩa mềm

Floppy.png

Cuối cùng, sử dụng Hộp sản phẩm widget trong MyHomePage tiện ích con như được chỉ định bên dưới –

class MyHomePage extends StatelessWidget { 
   MyHomePage({Key key, this.title}) : super(key: key); 
   final String title; 

   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title:Text("Product Listing")), 
         body: ListView(
            shrinkWrap: true, padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), 
            children: <Widget> [
               ProductBox(
                  name: "iPhone", 
                  description: "iPhone is the stylist phone ever", 
                  price: 1000, 
                  image: "iphone.png"
               ), 
               ProductBox(
                  name: "Pixel", 
                  description: "Pixel is the most featureful phone ever", 
                  price: 800, 
                  image: "pixel.png"
               ), 
               ProductBox( 
                  name: "Laptop", 
                  description: "Laptop is most productive development tool", 
                  price: 2000, 
                  image: "laptop.png"
               ), 
               ProductBox( 
                  name: "Tablet", 
                  description: "Tablet is the most useful device ever for meeting", 
                  price: 1500, 
                  image: "tablet.png"
               ), 
               ProductBox(
                  name: "Pendrive", 
                  description: "Pendrive is useful storage medium", 
                  price: 100, 
                  image: "pendrive.png"
               ), 
               ProductBox(
                  name: "Floppy Drive", 
                  description: "Floppy drive is useful rescue storage medium", 
                  price: 20, 
                  image: "floppy.png"
               ), 
            ],
         )
      );
   }
}
  • Ở đây, chúng tôi đã sử dụng Hộp sản phẩm là con của ListView tiện ích con.

  • Mã hoàn chỉnh (main.dart) của ứng dụng bố cục sản phẩm (product_layout_app) như sau –

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp()); 

class MyApp extends StatelessWidget { 
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) {
      return MaterialApp(
         title: 'Flutter Demo', theme: ThemeData(
            primarySwatch: Colors.blue,
         ), 
         home: MyHomePage(title: 'Product layout demo home page'), 
      );
   }
}
class MyHomePage extends StatelessWidget { 
   MyHomePage({Key key, this.title}) : super(key: key); 
   final String title; 
   
   @override 
   Widget build(BuildContext context) { 
      return Scaffold( 
         appBar: AppBar(title: Text("Product Listing")), 
         body: ListView(
            shrinkWrap: true, 
            padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), 
            children: <Widget>[ 
               ProductBox(
                  name: "iPhone", 
                  description: "iPhone is the stylist phone ever", 
                  price: 1000, 
                  image: "iphone.png"
               ), 
               ProductBox( 
                  name: "Pixel",    
                  description: "Pixel is the most featureful phone ever", 
                  price: 800, 
                  image: "pixel.png"
               ), 
               ProductBox( 
                  name: "Laptop", 
                  description: "Laptop is most productive development tool", 
                  price: 2000, 
                  image: "laptop.png"
               ), 
               ProductBox( 
                  name: "Tablet", 
                  description: "Tablet is the most useful device ever for meeting", 
                  price: 1500, 
                  image: "tablet.png"
               ), 
               ProductBox( 
                  name: "Pendrive", 
                  description: "Pendrive is useful storage medium", 
                  price: 100, 
                  image: "pendrive.png"
               ), 
               ProductBox(
                  name: "Floppy Drive", 
                  description: "Floppy drive is useful rescue storage medium", 
                  price: 20, 
                  image: "floppy.png"
               ), 
            ],
         )
      );
   }
}
class ProductBox extends StatelessWidget {
   ProductBox({Key key, this.name, this.description, this.price, this.image}) :
      super(key: key); 
   final String name; 
   final String description; 
   final int price; 
   final String image; 
   
   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), 
         height: 120, 
         child: Card(
            child: Row(
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               children: <Widget>[ 
                  Image.asset("assets/appimages/" + image), 
                  Expanded( 
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column(    
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(
                                 this.name, style: TextStyle(
                                    fontWeight: FontWeight.bold
                                 )
                              ),
                              Text(this.description), Text(
                                 "Price: " + this.price.toString()
                              ), 
                           ], 
                        )
                     )
                  )
               ]
            )
         )
      );
   }
}

Kết quả cuối cùng của ứng dụng như sau:

Danh sách sản phẩm