Flutter垂直滚动标签栏插件vertical_scroll_tabbar的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter垂直滚动标签栏插件vertical_scroll_tabbar的使用

特性

垂直滚动视图带有标签栏。 当滚动视图滚动时,会自动更改标签栏索引。 同时,点击标签栏项时,滚动视图会滚动到该标签栏项的顶部。

使用

VerticalScrollTabbar(
    tabs: [...],
    children: [...],
);

参数

参数 类型 描述 必须 默认值
tabs List 标签栏项
children List 滚动视图项
isScrollable bool 是否允许标签栏滚动 false
indicatorColor Color 选中标签下划线的颜色
onTabChanged Function 当标签索引改变时调用的回调函数
width double? 整个标签栏的宽度 null
height double? 整个标签栏的高度 null

要求

  • tabschildren 必须具有相同的长度。
  • children 必须具有 GlobalKey 作为键属性。

完整示例

import 'package:flutter/material.dart';
import 'package:vertical_scroll_tabbar/vertical_scroll_tabbar.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      home: Scaffold(
        body: SafeArea(
          child: VerticalScrollTabbar(
            isScrollable: true,
            indicatorColor: Colors.red,
            onTabChange: (index) {
              debugPrint(index.toString());
            },
            tabs: [
              Tab(
                child: Container(
                    alignment: Alignment.center,
                    width: 100,
                    child: const Text(
                      '男士服装',
                      style: TextStyle(color: Colors.black),
                    )),
              ),
              Tab(
                child: Container(
                    alignment: Alignment.center,
                    width: 100,
                    child: const Text(
                      '珠宝',
                      style: TextStyle(color: Colors.black),
                    )),
              ),
              Tab(
                child: Container(
                    alignment: Alignment.center,
                    width: 100,
                    child: const Text(
                      '电子产品',
                      style: TextStyle(color: Colors.black),
                    )),
              ),
              Tab(
                child: Container(
                    alignment: Alignment.center,
                    width: 120,
                    child: const Text(
                      '女士服装',
                      style: TextStyle(color: Colors.black),
                    )),
              ),
            ],
            children: [
              Column(
                key: GlobalKey(),
                children: [
                  Text('男士服装', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                  ...shoppingItems
                      .map((element) => element.category == '男士服装' ? ShoppingItemCard(item: element) :
                  const SizedBox()),
                      ]
              ),
              Column(key: GlobalKey(), children: [
                Text( '珠宝', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                ...shoppingItems
                    .map((element) => element.category == '珠宝' ? ShoppingItemCard(item: element) : const
                SizedBox())
              ]),
              Column(
                key: GlobalKey(),
                children: [
                  Text('电子产品', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                  ...shoppingItems.map(
                      (element) => element.category == '电子产品' ? ShoppingItemCard(item: element) : const
                      SizedBox())
                ],
              ),
              Column(
                key: GlobalKey(),
                children: [
                  Text('女士服装', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                  ...shoppingItems.map((element) =>
                      element.category == '女士服装' ? ShoppingItemCard(item: element) : const SizedBox())
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ShoppingItemCard extends StatelessWidget {
  const ShoppingItemCard({super.key, required this.item});

  final ShoppingItem item;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey),
        borderRadius: BorderRadius.circular(10),
      ),
      child: Row(
        children: [
          // 商品展示
          SizedBox(
            width: 170,
            height: 170,
            child: Padding(
              padding: const EdgeInsets.all(10),
              child: Image.network(item.image, fit: BoxFit.cover,
                  frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
                return AnimatedOpacity(
                  opacity: frame == null ? 0 : 1,
                  duration: const Duration(seconds: 1),
                  curve: Curves.easeOut,
                  child: ClipRRect(borderRadius: BorderRadius.circular(20), child: child),
                );
              }),
            ),
          ),
          // 商品详情
          const SizedBox(width: 20),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  item.title,
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                  ),
                  maxLines: 2,
                ),
                const SizedBox(height: 10),
                Text(
                  item.description,
                  style: const TextStyle(
                    fontSize: 14,
                    color: Colors.grey,
                    overflow: TextOverflow.ellipsis,
                  ),
                  maxLines: 2,
                ),
                const SizedBox(height: 10),
                Text(
                  '\$${item.price}',
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    overflow: TextOverflow.ellipsis,
                  ),
                  maxLines: 2,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter垂直滚动标签栏插件vertical_scroll_tabbar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter垂直滚动标签栏插件vertical_scroll_tabbar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的vertical_scroll_tabbar插件的使用,下面是一个示例代码案例,展示了如何在一个Flutter应用中实现垂直滚动的标签栏。这个示例假设你已经将vertical_scroll_tabbar插件添加到了你的pubspec.yaml文件中。

首先,确保你的pubspec.yaml文件中包含以下依赖:

dependencies:
  flutter:
    sdk: flutter
  vertical_scroll_tab_bar: ^x.y.z  # 请替换为最新版本号

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

接下来,是一个完整的Flutter应用示例,展示了如何使用VerticalScrollTabBarVerticalScrollTabBarView

import 'package:flutter/material.dart';
import 'package:vertical_scroll_tab_bar/vertical_scroll_tab_bar.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Vertical Scroll Tab Bar Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: VerticalTabBarDemo(),
    );
  }
}

class VerticalTabBarDemo extends StatefulWidget {
  @override
  _VerticalTabBarDemoState createState() => _VerticalTabBarDemoState();
}

class _VerticalTabBarDemoState extends State<VerticalTabBarDemo> {
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Vertical Scroll Tab Bar Demo'),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: Container(
              decoration: BoxDecoration(
                border: Border(
                  right: BorderSide(color: Colors.grey.shade300, width: 1.0),
                ),
              ),
              child: VerticalScrollTabBar(
                tabs: [
                  Tab(text: 'Tab 1'),
                  Tab(text: 'Tab 2'),
                  Tab(text: 'Tab 3'),
                  Tab(text: 'Tab 4'),
                  Tab(text: 'Tab 5'),
                  Tab(text: 'Tab 6'),
                  Tab(text: 'Tab 7'),
                  Tab(text: 'Tab 8'),
                ],
                controller: TabController(length: 8, vsync: this),
                labelColor: Colors.blue,
                unselectedLabelColor: Colors.grey,
                indicatorSize: TabBarIndicatorSize.label,
                indicatorPadding: EdgeInsets.zero,
                indicator: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(8.0),
                ),
                onTabSelected: (int index) {
                  setState(() {
                    selectedIndex = index;
                  });
                },
              ),
            ),
          ),
          Expanded(
            child: VerticalScrollTabBarView(
              controller: TabController(length: 8, vsync: this),
              children: [
                Center(child: Text('Content of Tab 1')),
                Center(child: Text('Content of Tab 2')),
                Center(child: Text('Content of Tab 3')),
                Center(child: Text('Content of Tab 4')),
                Center(child: Text('Content of Tab 5')),
                Center(child: Text('Content of Tab 6')),
                Center(child: Text('Content of Tab 7')),
                Center(child: Text('Content of Tab 8')),
              ],
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    // 清理TabController资源
    final TabController tabController = TabController.of(context, nullOk: false);
    tabController.dispose();
    super.dispose();
  }
}

代码解释:

  1. 依赖导入:确保pubspec.yaml文件中已经添加了vertical_scroll_tab_bar依赖。
  2. 主应用MyApp是一个简单的Material应用,设置了主题并指定了主页为VerticalTabBarDemo
  3. 状态管理VerticalTabBarDemo是一个有状态的小部件,它维护了一个selectedIndex变量来跟踪当前选中的标签。
  4. UI结构
    • 使用Column布局,将垂直滚动的标签栏和内容视图分开。
    • 标签栏使用VerticalScrollTabBar,内容视图使用VerticalScrollTabBarView
    • VerticalScrollTabBarVerticalScrollTabBarView共享同一个TabController来同步标签选择。
  5. 标签栏和内容:定义了8个标签和相应的内容视图。
  6. 资源清理:在dispose方法中释放TabController资源,以避免内存泄漏。

请注意,vertical_scroll_tab_bar插件的具体API可能会随着版本的更新而变化,因此请参考插件的官方文档以获取最新的使用指南和API参考。

回到顶部