Flutter混合列表标签栏插件sliver_tabbar_with_mixed_list的使用
Flutter混合列表标签栏插件sliver_tabbar_with_mixed_list的使用
SliverTabBarWithMixedList
一个提供可定制标签栏和包含不同高度项目的混合列表(包括父项目和子项目)的Flutter插件。如果最后一部分(父项目及其子项目)太短而无法达到屏幕顶部,该插件提供了可定制的底部填充缺失的空间。
安装
在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
sliver_tabbar_with_mixed_list: ^0.0.1
使用
在你的应用中使用SliverTabBarWithMixedList
小部件。根据需要自定义标签栏、列表项和底部。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:sliver_tabbar_with_mixed_list/sliver_tabbar_with_mixed_list.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'SliverTabBarWithMixedList Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'SliverTabBarWithMixedList Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<HeaderItem> sections = [];
double listHeaderHeight = 80;
double listHeaderSmallHeight = 40;
double listSubheaderHeight = 50;
double listItemHeight = 100;
double variantListItemHeight = 120;
[@override](/user/override)
void initState() {
super.initState();
double offsetStart = 0;
List<ChildItem> children = List.generate(
5,
(index) => Child(itemHeight: listItemHeight),
);
List<ChildItem> subChildren = List.generate(
3,
(index) => Child(itemHeight: listItemHeight),
);
List<ChildItem> subSubChildren = List.generate(
2,
(index) => Child(itemHeight: listItemHeight),
);
List<ChildItem> variantChildrean = List.generate(
4,
(index) => VariantChild(itemHeight: variantListItemHeight),
);
for (int i = 0; i < 11; i++) {
double offsetToAdd = 0;
Header header;
if (i < 10) {
header = Header(
key: ValueKey(i),
name: 'Header item $i',
offsetStart: offsetStart,
childrenCount: children.length,
itemHeight: listHeaderHeight,
childrenHeight: listItemHeight,
childrean: children,
subSections: List.generate(
3,
(index) {
var subSubSection = SubHeader(
key: ValueKey(index),
name: 'SubSubheader item $index',
offsetStart: offsetStart,
childrenCount: subSubChildren.length,
itemHeight: listSubheaderHeight,
childrenHeight: listItemHeight,
childrean: subSubChildren,
);
offsetToAdd += subSubSection.itemHeight +
(subSubSection.childrenHeight * subSubSection.childrenCount);
var section = SubHeader(
key: ValueKey(index),
name: 'Subheader item $index',
offsetStart: offsetStart,
childrenCount: subChildren.length,
itemHeight: listSubheaderHeight,
childrenHeight: listItemHeight,
subSections: [subSubSection],
childrean: subChildren,
);
offsetToAdd +=
listSubheaderHeight + (listItemHeight * subChildren.length);
return section;
},
),
);
} else {
header = Header(
key: ValueKey(i),
name: 'Header V item $i',
offsetStart: offsetStart,
childrenCount: children.length,
itemHeight: listHeaderSmallHeight,
childrenHeight: variantListItemHeight,
childrean: variantChildrean,
subSections: List.generate(
3,
(index) {
var subSubSection = SubHeader(
key: ValueKey(index),
name: 'SubSubheader V item $index',
offsetStart: offsetStart,
childrenCount: subSubChildren.length,
itemHeight: listSubheaderHeight,
childrenHeight: variantListItemHeight,
childrean: variantChildrean,
);
offsetToAdd += subSubSection.itemHeight +
(subSubSection.childrenHeight * subSubSection.childrenCount);
var section = SubHeader(
key: ValueKey(index),
name: 'Subheader V item $index',
offsetStart: offsetStart,
childrenCount: subChildren.length,
itemHeight: listSubheaderHeight,
childrenHeight: variantListItemHeight,
subSections: [subSubSection],
childrean: variantChildrean,
);
offsetToAdd += listSubheaderHeight +
(variantListItemHeight * subChildren.length);
return section;
},
),
);
}
offsetStart += offsetToAdd;
offsetToAdd = 0;
offsetStart +=
header.itemHeight + (header.childrenHeight * header.childrenCount);
header = Header.clone(header, offsetStart);
sections.add(header);
}
sections.last = Header.clone((sections.last as Header), double.infinity);
}
Widget buildHeader(BuildContext context, HeaderItem item) {
Header header = item as Header;
return Container(
color: Colors.orange,
child: Center(
child: Text(
header.name,
style: const TextStyle(fontSize: 30),
),
),
);
}
Widget buildSubHeader(BuildContext context, covariant SubheaderItem item) {
SubHeader header = item as SubHeader;
return Container(
color: Colors.green,
child: Center(
child: Text(
header.name,
style: const TextStyle(fontSize: 30),
),
),
);
}
Widget buildChild(BuildContext context, ChildItem item) {
return Container(
color: Colors.blue.shade400,
child: const Center(
child: Text(
'Child item',
style: TextStyle(fontSize: 20),
),
),
);
}
Widget buildVariantChild(
BuildContext context, covariant VariantChildItem item) {
return Container(
color: Colors.purple.shade400,
child: const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Variant Child item',
style: TextStyle(fontSize: 16),
),
Text(
'Variant Child Description',
style: TextStyle(fontSize: 12),
),
],
),
),
);
}
double itemExtentBuilder(
ListItem item, int index, SliverLayoutDimensions dimensions) {
return item.itemHeight;
}
[@override](/user/override)
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text(widget.title),
),
SliverTabBarWithMixedList(
controller: PrimaryScrollController.of(context),
indicatorPadding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 4.0,
),
tabBarIndicator: BoxDecoration(
borderRadius: BorderRadius.circular(
25.0,
),
color: Colors.green,
),
listHeaderHeight: listHeaderHeight,
listItemHeight: listItemHeight,
sections: sections,
headerBuilder: buildHeader,
subHeaderBuilder: buildSubHeader,
childBuilder: buildChild,
variantChildBuilder: buildVariantChild,
itemExtentBuilder: itemExtentBuilder,
)
],
),
),
);
}
}
class Header extends HeaderItem {
Header({
required super.key,
required this.name,
required super.offsetStart,
required super.itemHeight,
required super.childrenCount,
required super.childrenHeight,
super.childrean,
super.subSections,
});
final String name;
Header.params({
required super.key,
required this.name,
required super.offsetStart,
required super.itemHeight,
required super.childrenCount,
required super.childrenHeight,
required super.offsetEnd,
super.childrean,
super.subSections,
}) : super.params();
factory Header.clone(Header header, double offsetEnd) =>
Header.params(
key: header.key,
name: header.name,
offsetStart: header.offsetStart,
itemHeight: header.itemHeight,
childrenCount: header.childrenCount,
childrenHeight: header.childrenHeight,
offsetEnd: offsetEnd,
childrean: header.childrean,
subSections: header.subSections,
);
}
class SubHeader extends SubheaderItem {
SubHeader({
required super.key,
required this.name,
required super.offsetStart,
required super.itemHeight,
required super.childrenCount,
required super.childrenHeight,
super.childrean,
super.subSections,
}) : super();
final String name;
}
class Child extends ChildItem {
Child({required super.itemHeight});
}
class VariantChild extends VariantChildItem {
VariantChild({required super.itemHeight});
}
更多关于Flutter混合列表标签栏插件sliver_tabbar_with_mixed_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter混合列表标签栏插件sliver_tabbar_with_mixed_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 sliver_tabbar_with_mixed_list
插件的示例代码。这个插件允许你在 Flutter 中创建一个混合列表和标签栏的布局。首先,确保你已经在 pubspec.yaml
文件中添加了该依赖:
dependencies:
flutter:
sdk: flutter
sliver_tabbar_with_mixed_list: ^最新版本号 # 请替换为实际最新版本号
然后,运行 flutter pub get
来获取依赖。
接下来,下面是一个完整的示例代码,展示如何使用 SliverTabBarWithMixedList
创建一个混合列表和标签栏:
import 'package:flutter/material.dart';
import 'package:sliver_tabbar_with_mixed_list/sliver_tabbar_with_mixed_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SliverTabBarWithMixedList Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SliverTabBarWithMixedList Demo'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverTabBarWithMixedList(
controller: _tabController,
tabs: [
Tab(icon: Icon(Icons.directions_car), text: 'Tab 1'),
Tab(icon: Icon(Icons.directions_transit), text: 'Tab 2'),
],
sliverListHeaderBuilder: (BuildContext context, int index) {
return SliverPadding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
sliver: SliverToBoxAdapter(
child: Text(
'Header for Tab $index',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
);
},
sliverListBuilders: [
(BuildContext context, int index) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ListTile(
title: Text('Item $index in Tab 1'),
);
},
childCount: 20,
),
);
},
(BuildContext context, int index) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ListTile(
title: Text('Item $index in Tab 2'),
);
},
childCount: 20,
),
);
},
],
),
];
},
body: TabBarView(
controller: _tabController,
children: [
// 这里可以放置与 Tab 1 相关的额外内容(如果需要)
Container(),
// 这里可以放置与 Tab 2 相关的额外内容(如果需要)
Container(),
],
),
),
);
}
}
在这个示例中:
SliverTabBarWithMixedList
被用来创建一个带有标签栏和混合列表的布局。SliverTabBarWithMixedList
接受一个TabController
,用于控制标签栏的状态。tabs
属性定义了标签栏中的标签。sliverListHeaderBuilder
是一个函数,用于为每个标签页生成一个头部(例如,一个标题)。sliverListBuilders
是一个函数列表,每个函数负责生成对应标签页的列表内容。TabBarView
用于显示与每个标签页相关的额外内容(如果需要)。
这个示例展示了如何使用 sliver_tabbar_with_mixed_list
插件来创建一个带有混合列表和标签栏的布局。你可以根据需要进一步自定义和扩展这个示例。