我正在尝试构建一个将列表作为子项的选项卡式视图。
类别标签和列表内容都将从数据库中获取。
我正在从呼叫者页面传递标签,并成功地将它们作为列表传递。 现在,我正在尝试加载列表,并且构建了一个小部件(myList),该小部件成功返回了Future ListView。
问题有两个:
现在我的代码是这样:
import 'package:flutter/material.dart';
import 'package:flutter_app/ui/menu_category_list.dart';
// Each TabBarView contains a _Page and for each _Page there is a list
// of _CardData objects. Each _CardData object is displayed by a _CardItem.
List<Tab> Tabs(List<String> l){
List<Tab> list;
for (String c in l) {
list.add(new Tab(text: c));
}
return list;
}
class TabsDemo extends StatelessWidget {
const TabsDemo({ Key key , this.categorie}) : super(key: key);
final List<Tab> categorie;
@override
Widget build(BuildContext ctxt) {
return new MaterialApp(
title: "Nice app",
home: new DefaultTabController(
length: 5,
child: new Scaffold(
appBar: new AppBar(
title: new Text("Title"),
bottom: new TabBar(
tabs:
categories,
//new Tab(text: "First Tab"),
//new Tab(text: "Second Tab"),
),
),
body: new TabBarView(
children: [
new MenuCategoryList(),
new MenuCategoryList(),
new MenuCategoryList(),
new MenuCategoryList(),
new MenuCategoryList()
]
)
),
)
);
}
}
非常感谢
答案 0 :(得分:3)
您可以使用List<E>.generate
来实现。
import 'package:flutter/material.dart';
假设您从呼叫者页面传递了一组类别。假设这是您的类别列表。
List<String> categories = ["a", "b", "c", "d", "e", "f", "g", "h"];
然后您可以执行类似的操作来实现您想要的。
class TabsDemo extends StatefulWidget {
@override
_TabsDemoState createState() => _TabsDemoState();
}
class _TabsDemoState extends State<TabsDemo> {
TabController _controller;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext ctxt) {
return new MaterialApp(
home: DefaultTabController(
length: categories.length,
child: new Scaffold(
appBar: new AppBar(
title: new Text("Title"),
bottom: new TabBar(
isScrollable: true,
tabs: List<Widget>.generate(categories.length, (int index){
print(categories[0]);
return new Tab(icon: Icon(Icons.directions_car), text: "some random text");
}),
),
),
body: new TabBarView(
children: List<Widget>.generate(categories.length, (int index){
print(categories[0]);
return new Text("again some random text");
}),
)
))
);
}
您还可以将不同组的小部件设置为“选项卡”的视图。您可以创建页面列表并遵循相同的方法。
答案 1 :(得分:2)
绝对是"servicebus_1_connectionString": {
"type": "securestring",
"metadata": {
"description": "Azure Service Bus Connection String"
}
},
---
"dependsOn": [
"[resourceId('Microsoft.Web/connections', parameters('servicebus_1_Connection_Name'))]"
]
},
{
"type": "MICROSOFT.WEB/CONNECTIONS",
"apiVersion": "2016-06-01",
"name": "[parameters('servicebus_1_Connection_Name')]",
"location": "westeurope",
"properties": {
"api": {
"id": "[concat(subscription().id, '/providers/Microsoft.Web/locations/', 'westeurope', '/managedApis/', 'servicebus')]"
},
"displayName": "[parameters('servicebus_1_Connection_DisplayName')]",
"parameterValues": {
"connectionString": "[parameters('servicebus_1_connectionString')]"
}
}
最好的解决方案。
如果需要修改阵列,则会出现问题。它们的事实在于,在修改数组时,您没有机会使用相同的控制器。
在这种情况下,您可以使用下一个自定义小部件:
List<E>.generate
答案 2 :(得分:0)
空安全版本
import 'package:flutter/material.dart';
class CustomTabView extends StatefulWidget {
final int? itemCount;
final IndexedWidgetBuilder? tabBuilder;
final IndexedWidgetBuilder? pageBuilder;
final Widget? stub;
final ValueChanged<int>? onPositionChange;
final ValueChanged<double>? onScroll;
final int? initPosition;
CustomTabView({this.itemCount, this.tabBuilder, this.pageBuilder, this.stub,
this.onPositionChange, this.onScroll, this.initPosition});
@override
_CustomTabsState createState() => _CustomTabsState();
}
class _CustomTabsState extends State<CustomTabView> with TickerProviderStateMixin {
late TabController controller;
late int _currentCount;
late int _currentPosition;
@override
void initState() {
_currentPosition = widget.initPosition!;
controller = TabController(
length: widget.itemCount!,
vsync: this,
initialIndex: _currentPosition,
);
controller.addListener(onPositionChange);
controller.animation!.addListener(onScroll);
_currentCount = widget.itemCount!;
super.initState();
}
@override
void didUpdateWidget(CustomTabView oldWidget) {
if (_currentCount != widget.itemCount) {
controller.animation!.removeListener(onScroll);
controller.removeListener(onPositionChange);
controller.dispose();
if (widget.initPosition != null) {
_currentPosition = widget.initPosition!;
}
if (_currentPosition > widget.itemCount! - 1) {
_currentPosition = widget.itemCount! - 1;
_currentPosition = _currentPosition < 0 ? 0 :
_currentPosition;
if (widget.onPositionChange is ValueChanged<int>) {
WidgetsBinding.instance!.addPostFrameCallback((_){
if(mounted) {
widget.onPositionChange!(_currentPosition);
}
});
}
}
_currentCount = widget.itemCount!;
setState(() {
controller = TabController(
length: widget.itemCount!,
vsync: this,
initialIndex: _currentPosition,
);
controller.addListener(onPositionChange);
controller.animation!.addListener(onScroll);
});
} else if (widget.initPosition != null) {
controller.animateTo(widget.initPosition!);
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
controller.animation!.removeListener(onScroll);
controller.removeListener(onPositionChange);
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (widget.itemCount! < 1) return widget.stub ?? Container();
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
alignment: Alignment.center,
child: TabBar(
isScrollable: true,
controller: controller,
labelColor: Theme.of(context).primaryColor,
unselectedLabelColor: Theme.of(context).hintColor,
indicator: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).primaryColor,
width: 2,
),
),
),
tabs: List.generate(
widget.itemCount!,
(index) => widget.tabBuilder!(context, index),
),
),
),
Expanded(
child: TabBarView(
controller: controller,
children: List.generate(
widget.itemCount!,
(index) => widget.pageBuilder!(context, index),
),
),
),
],
);
}
onPositionChange() {
if (!controller.indexIsChanging) {
_currentPosition = controller.index;
if (widget.onPositionChange is ValueChanged<int>) {
widget.onPositionChange!(_currentPosition);
}
}
}
onScroll() {
if (widget.onScroll is ValueChanged<double>) {
widget.onScroll!(controller.animation!.value);
}
}
}