Flutter Tab là gì

    TAB là một bố cục giao diện nằm trong đối tượng TabBar, TabBar chứa nhiều Tab và thường được dùng để phân loại các Widget có cùng tính chất với nhau vào cùng một Tab

    Tab được sử dụng gắn liền với TabController, TabBar, TabBarView

    TabController

    TabController có nhiệm vụ đồng bộ hóa các TAB trong suốt quá trình hoạt động, TabController có thể được tạo ra một cách thủ công hoặc sử dụng Widget có sẵn là DefaultTabController, DefaultTabController hỗ trợ các tính năng cơ bản như khai bản như định nghĩa số lượng các Tab

    DefaultTabController(
      // The number of tabs / content sections to display.
      length: 3,
      child: // Complete this code in the next step.
    );
    

    TabBar

    TabBar dùng để chứa các Tab, tạo ra các Tab, hãy xem hình dưới đây để có thể hình dung rõ hơn về mối quan hệ giữa TabBar và Tab

    TabBar in Flutter

    DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: [
              Tab(icon: Icon(Icons.directions_car)),
              Tab(icon: Icon(Icons.directions_transit)),
              Tab(icon: Icon(Icons.directions_bike)),
            ],
          ),
        ),
      ),
    );
    

    Trong ví dụ trên chúng ta đã sử dụng DefaultTabController để chứa một TabBar, trong TabBar lại có chứa 3 Tab

    Câu hỏi đặt ra là bạn có thể đặt nhiều TabBar trong một DefaultTabController không? Flutter sẽ hỗ trợ bạn việc này tuy nhiên DefaultTabController chỉ làm việc với một TabBar gần với nó nhất, để hoạt động được nhiều TabBar bạn hãy dùng đến TabController được điều khiển bởi chính bạn (điều khiển thủ công)

    TabBarView

    Sử dụng TabBarView để chứa các nội dung tương ứng với mỗi Tab trên TabBar.

    TabBarView (
      children: [
        Icon(Icons.directions_car),
        Icon(Icons.directions_transit),
        Icon(Icons.directions_bike),
      ],
    );
    

    Ví dụ TabBar

    Trong ví dụ này chúng ta sẽ tạo ra một TabBar chứa 3 Tab và sử dụng DefaultTabController

    Flutter TabBar Sample

    Cấu trúc TabController, DefaultTabController, TabBar 

    TabController

    TabController(
        {int initialIndex: 0,
        @required int length,
        @required TickerProvider vsync}
    )
    

    DefaultTabController

    const DefaultTabController(
        {Key key,
        @required int length,
        int initialIndex: 0,
        @required Widget child}
    )

    TabBar

    const TabBar(
        {Key key,
        @required List tabs,
        TabController controller,
        bool isScrollable: false,
        Color indicatorColor,
        double indicatorWeight: 2.0,
        EdgeInsetsGeometry indicatorPadding: EdgeInsets.zero,
        Decoration indicator,
        TabBarIndicatorSize indicatorSize,
        Color labelColor,
        TextStyle labelStyle,
        EdgeInsetsGeometry labelPadding,
        Color unselectedLabelColor,
        TextStyle unselectedLabelStyle,
        DragStartBehavior dragStartBehavior: DragStartBehavior.start,
        MouseCursor mouseCursor,
        ValueChanged onTap,
        ScrollPhysics physics}
    )

    TabBarView

    const TabBarView(
        {Key key,
        @required List children,
        TabController controller,
        ScrollPhysics physics,
        DragStartBehavior dragStartBehavior: DragStartBehavior.start}
    )

    Các thuộc tính trong Flutter TabBar

    isScrollable

    isScrollable property

    Thuộc tính isScrollable  có hay không cho phép tạo thanh cuộn ngang khi tổng chiều dài của các tab lớn hơn độ rộng màn hình. khi isScrollable được gán là True thì độ rộng của mỗi tab chứa vừa đủ nội dung của tab (Hình ảnh và văn bản) và xuất hiện thanh trượt ngang

    Bạn hãy xem ví dụ dưới đây

    flutter isScrollable

    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: 'Title of Application',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      MyHomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        EdgeInsets a2; EdgeInsetsDirectional a;
        return DefaultTabController(
            length: 6,
            child: Scaffold(
              appBar: AppBar(
                bottom: createTabBar(),
                title: Text('Flutter TabBar Example'),
              ),
              body: TabBarView(
                children: [
                  Center(child: Text("Car")),
                  Center(child: Text("Transit")),
                  Center(child: Text("Bike")),
                  Center(child: Text("Boat")),
                  Center(child: Text("Railway")),
                  Center(child: Text("Bus Electrical"))
                ],
              ),
            )
        );
      }
    
      TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
          isScrollable: true,
        );
      }
    }

    indicatorColor

    Thuộc tính indicatorColor dùng để định dạng đường kẻ nền Tab đang được chọn, thuộc tính này sẽ bị vô hiệu lực nếu thuộc tính indicator được sử dụng

    indicatorColor: Color(0xffE74C3C),

    Ví dụ dưới đây sẽ tạo ra một đường kẻ (Line) màu đỏ khi tab được chọn

    flutter indicatorColor

    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: 'Title of Application',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      MyHomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        EdgeInsets a2; EdgeInsetsDirectional a;
        return DefaultTabController(
            length: 6,
            child: Scaffold(
              appBar: AppBar(
                bottom: createTabBar(),
                title: Text('Flutter TabBar Example'),
              ),
              body: TabBarView(
                children: [
                  Center(child: Text("Car")),
                  Center(child: Text("Transit")),
                  Center(child: Text("Bike")),
                  Center(child: Text("Boat")),
                  Center(child: Text("Railway")),
                  Center(child: Text("Bus Electrical"))
                ],
              ),
            )
        );
      }
    
      TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
          /*isScrollable: true,*/
          indicatorColor: Color(0xffE74C3C),
        );
      }
    }

    indicatorWeight

    Thuộc tính indicatorWeight dùng để định dạng độ dày (Thickness) của đường kẻ (Line) phía dưới của Tab đang được chon

     indicatorWeight: 10

     

    Ví dụ dưới đây sẽ định dạng độ dày của đường kẻ (Line) lên 10 đơn vị khi tab được chọn

    flutter indicatorWeight

    TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
          /*isScrollable: true,*/
          indicatorColor: Color(0xffE74C3C),
          indicatorWeight: 10,
        );
      }
    }
    

    indicatorPadding

    Thuộc tính indicatorPadding dùng để chỉ định khoảng cách đệm (padding) của thanh ngang tới mép bên phải của tab

    indicatorPadding: EdgeInsets.only(right: 20),

    flutter indicatorPadding

    TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
          /*isScrollable: true,*/
          indicatorColor: Color(0xffE74C3C),
          indicatorWeight: 10,
          indicatorPadding: EdgeInsets.only(right: 20),
        );
      }
    }
    

    indicator

    Thuộc tính indicator dùng để tạo hiệu ức khung cho Tab đang được chọn, khi thuộc tính indicator được sử dụng thì các thuộc tính indicatorColor, indicatorWeightindicatorPadding sẽ bị vô hiệu hóa.

    flutter indication digram

     

    Sau đây là ví dụ cách dùng indicator

    TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
    
            indicator: ShapeDecoration (
                shape: UnderlineInputBorder (
                    borderSide: BorderSide(
                        color: Colors.transparent,
                        width: 0,
                        style: BorderStyle.solid
                    )
                ),
                gradient: LinearGradient(colors: [Color(0xff0081ff), Color(0xff01ff80)])
            )
        );
      }
    }
    

    flutter indicator sample

     

    labelColor, unselectedLabelColor

    thuộc tính labelColor dùng để chỉ định màu văn bản cho tab đang được chọn, thuộc tính unselectedLabelColor dùng để chỉ định màu cho các tab không được chọn

    Color labelColor;
    Color unselectedLabelColor;

    Chúng ta cùng tìm hiểu và xem kết quả ở ví dụ sau đây

    flutter labelColor

    TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
            labelColor: Colors.red,
            unselectedLabelColor: Colors.black,
        );
      }
    }
    

    labelPadding

    Thuộc tính labelPadding dùng để thêm vùng đệm (padding) vào cho các lable của từng tab

    labelPadding: EdgeInsets.all( 20),

    Cùng xem ví dụ sau nhé

    flutter labelPadding property

    TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
          labelPadding: EdgeInsets.all( 20),
    
        );
      }
    }
    

    labelStyle, unselectedLabelStyle

    Thuộc tính labelStyle, unselectedLabelStyle dùng để định dạng văn bản (lable) khi tab đang được chọn hoặc không chọn

     

    Trong vì dụ này lable được chọn sẽ được bôi đậm và có kích thước font size là 20, những lable không được chọn sẽ có font size là 18 và chữ thường

    flutter lableStyle property

    TabBar createTabBar()  {
        return TabBar(
          tabs: [
            Row (children: [Icon(Icons.directions_car), SizedBox(width:5), Text("Car")]),
            Row (children: [Icon(Icons.directions_transit), SizedBox(width:5), Text("Transit")]),
            Row (children: [Icon(Icons.directions_bike), SizedBox(width:5), Text("Bike")]),
            Row (children: [Icon(Icons.directions_boat), SizedBox(width:5), Text("Boat")]),
            Row (children: [Icon(Icons.directions_railway), SizedBox(width:5), Text("Railway")]),
            Row (children: [Icon(Icons.directions_bus), SizedBox(width:5), Text("Bus Electrical")]),
          ],
          labelStyle: TextStyle(fontWeight: FontWeight.bold, fontSize: 22),
          unselectedLabelStyle: TextStyle(fontStyle: FontStyle.normal, fontSize: 18),
        );
      }
    }
    

    onTap

    onTap là một sự kiện (hàm) callback sẽ được gọi khi người dùng lựa chọn Tab trên TabBar

    Chúng ta sẽ làm một ví dụ khi Tab được chọn sẽ đếm số lần Tab được chọn và ghi lại trên lable của Tab

    flutter onTab

    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: 'Title of Application',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key? key}) : super(key: key);
    
      @override
      State createState() {
        return MyHomePageState();
      }
    }
    
    class MyHomePageState extends State {
      int carClick = 0;
      int transitClick = 0;
      int bikeClick = 0;
    
      @override
      Widget build(BuildContext context) {
        return DefaultTabController(
            length: 3,
            child: Scaffold(
              appBar: AppBar(
                bottom: createTabBar(),
                title: Text('VTS OnTap Example'),
              ),
              body: TabBarView(
                children: [
                  Center(child: Text("Car")),
                  Center(child: Text("Transit")),
                  Center(child: Text("Bike"))
                ],
              ),
            )
        );
      }
    
      TabBar createTabBar()  {
        return TabBar(
            isScrollable: true,
            labelStyle: TextStyle(fontSize: 20),
            tabs: [
              Text("Car " + this.carClick.toString()),
              Text("Transit " + this.transitClick.toString()),
              Text("Bike " + this.bikeClick.toString())
            ],
            onTap: (index) {
              this.onTapHandler(index);
            }
        );
      }
    
      void onTapHandler(int index)  {
        setState(()  {
          switch(index){
            case 0:
              carClick++;
              break;
            case 1:
              transitClick++;
              break;
            case 2:
              bikeClick++;
              break;
          }
        });
      }
    
    

    Trên đây là toàn bộ hướng dẫn chi tiết sử dụng Flutter TabBar, Các bạn có câu hỏi gì liên hệ với tác giả Mr Dũng 098 333 0380. Các bạn mong muốn trở thành lập trình viên trên Mobile liên hệ công ty VTS chúng tôi nhận thực tập sinh hướng dẫn chi tiết lập trình Flutter từ A-Z