Flutter自定义标签布局插件smart_tab_layout的使用

smart_tab_layout是一个功能强大的 Flutter 插件,用于实现自定义标签布局。它提供了丰富的功能扩展,包括纵轴排列、灵活的样式配置以及多种指示器样式。


SmartTabLayout 使用

导入项目

pubspec.yaml 文件中添加依赖:

dependencies:
   smart_tab_layout: 1.0.7

然后运行 flutter pub get 来安装依赖。


创建

基本用法

  1. 外部定义一个 DefaultTabController 或传入一个控制器。
  2. 传入 labels 指定标签显示内容(可自定义标签样式通过 itemBuilderchildCount)。

示例代码:

DefaultTabController(
  length: 10,
  child: SmartTabLayout(
    labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
  ),
);

var controller = TabController(length: 10, vsync: this);

SmartTabLayout(
  controller: controller,
  itemBuilder: (context, index) {
    return Text(index.toString());
  },
  childCount: 10,
);

Tab 样式

可以通过多种参数来自定义标签的外观。

示例代码:

DefaultTabController(
  length: 10,
  child: SmartTabLayout(
    width: 400, // tabLayout 宽度
    height: 80, // tabLayout 高度
    space: 20, // tab 间隔
    background: Colors.lightBlue, // tabLayout 背景
    margin: EdgeInsets.only(left: 10), // tabLayout 外边距
    padding: EdgeInsets.only(left: 10, right: 10), // tabLayout 内边距
    borderRadius: BorderRadius.circular(6), // tabLayout 圆角
    border: Border.all(color: Colors.black, width: 1), // tabLayout 边框
    direction: Axis.horizontal, // tabLayout 方向
    itemWidth: 60, // tab 宽度
    itemHeight: 30, // tab 高度
    itemBackground: Colors.indigoAccent, // tab 背景
    itemBorderRadius: BorderRadius.circular(8), // tab 圆角
    itemPadding: EdgeInsets.symmetric(horizontal: 6, vertical: 3), // tab 内边距
    itemBorder: Border.all(color: Colors.black, width: 1), // tab 边框
    isScrollable: true, // tab 是否滚动
    itemSelectedBackground: Colors.white, // tab 选中背景
    itemSelectedBorder: Border.all(color: Colors.orange, width: 1), // tab 选中边框
    itemSelectedBorderRadius: BorderRadius.zero, // tab 选中圆角
    itemSelectedPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 1), // tab 选中内边距
    itemTextStyle: TextStyle( // tab 字体样式
      color: Colors.purple,
      fontSize: 16,
      fontWeight: FontWeight.normal,
    ),
    itemSelectedTextStyle: TextStyle( // tab 选中字体样式
      color: Colors.orange,
      fontSize: 16,
      fontWeight: FontWeight.normal,
    ),
    childCount: 10, // 自定义 tab 数量
    itemBuilder: (c, i) { // 自定义 tab
      return Text(i.toString()); // 不设置 style 会继承默认样式
    },
  ),
);

指示器样式

可以自定义指示器的样式,例如使用图片作为指示器。

示例代码:

SmartImageTabIndicator.load("assets/img/ic_search.png", Size(20, 20)).then((value) {
  _image = value;
  setState(() {});
});

DefaultTabController(
  length: 10,
  child: SmartTabLayout(
    labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
    indicator: SmartImageTabIndicator(
      image: _image, // 自定义图片指示器
    ),
    indicatorSize: TabBarIndicatorSize.tab, // tab:indicator 宽度等于 tab 宽度
    indicatorBorderRadius: BorderRadius.vertical(top: Radius.circular(4)), // 指示器圆角
    indicatorColor: Colors.blue, // 指示器颜色
    indicatorWeight: 2, // 指示器高度
    indicatorPadding: EdgeInsets.only(bottom: 2), // 指示器位置
  ),
);

完整示例 Demo

以下是一个完整的示例代码,展示如何使用 smart_tab_layout 插件。

import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:smart_tab_layout/smart_tab_layout.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: Locale("zh_CN"),
      title: 'SmartTabLayout Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TestPage(),
    );
  }
}

class TestPage extends StatefulWidget {
  [@override](/user/override)
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> with TickerProviderStateMixin {
  TabController? tabController;
  TabController? tabController1;
  DrawableRoot? svgRoot;
  ui.Image? _image;

  [@override](/user/override)
  void initState() {
    super.initState();
    tabController = TabController(initialIndex: 7, length: 10, vsync: this);
    tabController1 = TabController(initialIndex: 7, length: 15, vsync: this);

    SmartImageTabIndicator.load("assets/img/ic_search.png", Size(20, 20))
        .then((value) {
      _image = value;
      setState(() {});
    });
    loadSvg();
  }

  loadSvg() async {
    final String rawSvg = 'assets/img/ic_airplane.svg';
    ByteData data = await rootBundle.load(rawSvg);

    svgRoot = await svg.fromSvgBytes(data.buffer.asUint8List(), rawSvg);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: SafeArea(
          child: _testList(),
        ),
      ),
    );
  }

  _testList() {
    return Column(
      children: [
        _tabStyle1(),
        SizedBox(height: 30),
        _tabStyle2(),
        SizedBox(height: 30),
        _tabStyle3(),
        SizedBox(height: 30),
        _tabBar(),
        SizedBox(height: 30),
        Row(
          children: [
            DefaultTabController(length: 10, child: _tabStyle4()),
            SizedBox(width: 30),
            DefaultTabController(length: 15, child: _tabStyle5()),
          ],
        ),
      ],
    );
  }

  _tabStyle1() {
    return DefaultTabController(
      length: 10,
      child: SmartTabLayout(
        height: 80,
        itemTextStyle: TextStyle(fontWeight: FontWeight.normal, color: Colors.black),
        itemSelectedTextStyle: TextStyle(fontWeight: FontWeight.w500, color: Colors.black),
        indicator: SmartImageTabIndicator(
          customDraw: (canvas, offset, configuration, rect) async {
            canvas.translate(rect.topCenter.dx - 10, rect.topCenter.dy);
            svgRoot?.scaleCanvasToViewBox(canvas, Size(20, 20));
            svgRoot?.clipCanvasToViewBox(canvas);
            svgRoot?.draw(canvas, Rect.zero);
          },
        ),
        labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
      ),
    );
  }

  _tabStyle2() {
    return DefaultTabController(
      length: 10,
      child: SmartTabLayout(
        labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
        width: 400,
        height: 80,
        space: 20,
        spaceBuilder: (c, index) => Container(color: Colors.amber, width: 20),
        background: Colors.lightBlue,
        margin: EdgeInsets.only(left: 10, right: 10),
        padding: EdgeInsets.only(left: 10, right: 10),
        borderRadius: BorderRadius.circular(6),
        border: Border.all(color: Colors.black, width: 1),
        itemWidth: 60,
        itemHeight: 30,
        itemBackground: Colors.indigoAccent,
        itemBorderRadius: BorderRadius.circular(8),
        itemPadding: EdgeInsets.symmetric(horizontal: 6, vertical: 3),
        itemBorder: Border.all(color: Colors.black, width: 1),
        isScrollable: true,
        direction: Axis.horizontal,
        itemSelectedBackground: Colors.white,
        itemSelectedBorder: Border.all(color: Colors.orange, width: 1),
        itemSelectedBorderRadius: BorderRadius.zero,
        itemSelectedPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 1),
        itemTextStyle: TextStyle(
          color: Colors.purple,
          fontSize: 16,
          fontWeight: FontWeight.normal,
        ),
        itemSelectedTextStyle: TextStyle(
          color: Colors.orange,
          fontSize: 20,
          fontWeight: FontWeight.normal,
        ),
        childCount: 10,
        indicatorColor: Colors.redAccent,
      ),
    );
  }

  _tabStyle3() {
    return DefaultTabController(
      length: 15,
      child: SmartTabLayout(
        controller: tabController1,
        background: Colors.orangeAccent,
        indicatorSize: TabBarIndicatorSize.label,
        indicatorBorderRadius: BorderRadius.circular(4),
        padding: EdgeInsets.symmetric(horizontal: 10),
        width: 400,
        height: 80,
        space: 20,
        itemWidth: 40,
        itemTextStyle: TextStyle(
          color: Colors.black,
        ),
        itemSelectedTextStyle: TextStyle(
          color: Colors.redAccent,
        ),
        itemHeight: 30,
        isScrollable: true,
        childCount: 15,
        itemBuilder: (c, i) {
          return Container(
            alignment: Alignment.center,
            color: Colors.grey,
            child: Text(i.toString() + (i == 0 ? "23123" : "")),
          );
        },
        onTap: (index) {
          tabController?.index = index;
        },
      ),
    );
  }

  _tabBar() {
    return DefaultTabController(
      length: 10,
      child: TabBar(
        controller: tabController,
        isScrollable: true,
        labelColor: Colors.black,
        unselectedLabelColor: Colors.redAccent,
        onTap: (index) {
          tabController?.index = index;
        },
        indicatorSize: TabBarIndicatorSize.label,
        tabs: [
          Container(child: Text("113")),
          Text("22"),
          Text("33"),
          Text("44"),
          Text("55"),
          Text("66"),
          Text("77"),
          Text("88"),
          Text("99"),
          Text("101"),
        ],
      ),
    );
  }

  _tabStyle4() {
    return SmartTabLayout(
      width: 80,
      height: 400,
      space: 20,
      background: Colors.lightBlue,
      margin: EdgeInsets.only(left: 10),
      padding: EdgeInsets.all(10),
      borderRadius: BorderRadius.circular(6),
      border: Border.all(color: Colors.black, width: 1),
      itemWidth: 60,
      itemHeight: 30,
      itemBackground: Colors.indigoAccent,
      itemBorderRadius: BorderRadius.circular(8),
      itemPadding: EdgeInsets.symmetric(horizontal: 6, vertical: 3),
      itemBorder: Border.all(color: Colors.black, width: 1),
      isScrollable: true,
      direction: Axis.vertical,
      itemSelectedBackground: Colors.white,
      itemSelectedBorder: Border.all(color: Colors.orange, width: 1),
      itemSelectedBorderRadius: BorderRadius.zero,
      itemSelectedPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 1),
      itemTextStyle: TextStyle(
        color: Colors.purple,
        fontSize: 16,
        fontWeight: FontWeight.normal,
      ),
      itemSelectedTextStyle: TextStyle(
        color: Colors.orange,
        fontSize: 16,
        fontWeight: FontWeight.normal,
      ),
      childCount: 10,
      itemTransition: true,
      itemBuilder: (c, i) {
        return Container(
          alignment: Alignment.center,
          child: Text(i.toString()),
        );
      },
      indicatorWeight: 0,
    );
  }

  _tabStyle5() {
    return SmartTabLayout(
      labels: [
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "10",
        "11",
        "12",
        "13",
        "14",
        "15",
      ],
      controller: tabController1,
      indicatorSize: TabBarIndicatorSize.tab,
      width: 80,
      height: 400,
      space: 20,
      background: Colors.orangeAccent,
      padding: EdgeInsets.symmetric(vertical: 10),
      itemWidth: 40,
      itemTextStyle: TextStyle(
        color: Colors.black,
      ),
      itemSelectedTextStyle: TextStyle(
        color: Colors.redAccent,
      ),
      direction: Axis.vertical,
      indicatorWidth: 30,
      indicatorWeight: 5,
      indicatorBorderRadius: BorderRadius.horizontal(left: Radius.circular(4)),
      isScrollable: true,
      itemBuilder: (c, i) {
        return Container(
          height: i == 6 ? 80 : 30,
          alignment: Alignment.center,
          child: Text(i.toString()),
        );
      },
    );
  }
}

更多关于Flutter自定义标签布局插件smart_tab_layout的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义标签布局插件smart_tab_layout的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


smart_tab_layout 是一个用于 Flutter 的自定义标签布局插件,它提供了灵活的标签布局和丰富的自定义选项,可以帮助你轻松实现各种复杂的标签布局效果。以下是如何使用 smart_tab_layout 的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 smart_tab_layout 的依赖:

dependencies:
  flutter:
    sdk: flutter
  smart_tab_layout: ^latest_version

然后运行 flutter pub get 来安装依赖。

2. 导入包

在你的 Dart 文件中导入 smart_tab_layout 包:

import 'package:smart_tab_layout/smart_tab_layout.dart';

3. 使用 SmartTabLayout

SmartTabLayout 是一个灵活的标签布局组件,你可以通过它来创建自定义的标签布局。以下是一个简单的示例:

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  TabController _tabController;

  [@override](/user/override)
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
  }

  [@override](/user/override)
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Smart Tab Layout Example'),
        bottom: SmartTabBar(
          controller: _tabController,
          tabs: [
            SmartTab(text: 'Tab 1'),
            SmartTab(text: 'Tab 2'),
            SmartTab(text: 'Tab 3'),
          ],
        ),
      ),
      body: SmartTabBarView(
        controller: _tabController,
        children: [
          Center(child: Text('Content of Tab 1')),
          Center(child: Text('Content of Tab 2')),
          Center(child: Text('Content of Tab 3')),
        ],
      ),
    );
  }
}

4. 自定义选项

SmartTabLayout 提供了多种自定义选项,例如:

  • 标签样式:你可以通过 SmartTabtexticonchild 等属性来自定义标签的样式。
  • 标签栏样式:你可以通过 SmartTabBarindicatorColorindicatorWeightlabelColorunselectedLabelColor 等属性来自定义标签栏的样式。
  • 标签视图:你可以通过 SmartTabBarViewchildren 属性来设置每个标签对应的内容。

5. 更多高级功能

smart_tab_layout 还支持更多高级功能,例如:

  • 动态添加/删除标签:你可以通过 TabController 动态添加或删除标签。
  • 自定义标签布局:你可以通过 SmartTabBarisScrollable 属性来控制标签是否可滚动,或者通过 tabAlignment 属性来设置标签的对齐方式。

6. 示例代码

以下是一个更复杂的示例,展示了如何使用 smart_tab_layout 实现动态添加/删除标签的功能:

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  TabController _tabController;
  List<String> _tabs = ['Tab 1', 'Tab 2', 'Tab 3'];

  [@override](/user/override)
  void initState() {
    super.initState();
    _tabController = TabController(length: _tabs.length, vsync: this);
  }

  [@override](/user/override)
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  void _addTab() {
    setState(() {
      _tabs.add('Tab ${_tabs.length + 1}');
      _tabController = TabController(length: _tabs.length, vsync: this);
    });
  }

  void _removeTab() {
    if (_tabs.length > 1) {
      setState(() {
        _tabs.removeLast();
        _tabController = TabController(length: _tabs.length, vsync: this);
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Smart Tab Layout Example'),
        bottom: SmartTabBar(
          controller: _tabController,
          isScrollable: true,
          tabs: _tabs.map((tab) => SmartTab(text: tab)).toList(),
        ),
      ),
      body: SmartTabBarView(
        controller: _tabController,
        children: _tabs.map((tab) => Center(child: Text('Content of $tab'))).toList(),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: _addTab,
            child: Icon(Icons.add),
          ),
          SizedBox(height: 10),
          FloatingActionButton(
            onPressed: _removeTab,
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}
回到顶部