当我更改选项卡时调用基于文本小部件的构建
Call build on Text widget when i change tab
当我从一个选项卡切换到另一个选项卡时,我想更改 appBar 中的标题。在我当前的代码中不要这样做,因为在更改选项卡上不会调用构建。
感谢大家!!
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/task.dart';
import '../widgets/tasks_list_mob.dart';
import '../widgets/new_task.dart';
class TaskListName {
final String shortName;
final String longName;
TaskListName(this.shortName, this.longName);
}
class TaksScreen extends StatefulWidget {
@override
_TaksScreenState createState() => _TaksScreenState();
}
class _TaksScreenState extends State with TickerProviderStateMixin {
TabController _tabController;
final Map tasksListLabels = {
0: TaskListName('Backlog', 'Tasks in backlog'),
1: TaskListName('Tomorrow', 'Planed tasks for tomorrow'),
2: TaskListName('Today', 'Your tasks for today'),
3: TaskListName('Last work day', 'Tasks completed last working day'),
4: TaskListName('Completed', 'Completed Tasks'),
5: TaskListName('Backlog', 'Archived not completed tasks'),
};
@override
void initState() {
super.initState();
_tabController = TabController(length: 6, vsync: this, initialIndex: 2);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
Future showAddTaskDialog(BuildContext context) async {
print(_tabController);
await showDialog(
context: context,
builder: (context) => SimpleDialog(
children: [NewTask(TaksBucket.backlog)],
),
);
}
@override
Widget build(BuildContext context) {
final tasks = Provider.of>(context);
return Scaffold(
appBar: AppBar(
title: Text(tasksListLabels[_tabController.index].longName),
bottom: TabBar(
controller: _tabController,
isScrollable: true,
tabs: [
Tab(text: tasksListLabels[0].shortName),
Tab(text: tasksListLabels[1].shortName),
Tab(text: tasksListLabels[2].shortName),
Tab(text: tasksListLabels[3].shortName),
Tab(text: tasksListLabels[4].shortName),
Tab(text: tasksListLabels[5].shortName),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
TasksListMob(tasks, TaksBucket.backlog),
TasksListMob(tasks, TaksBucket.tomorrow),
TasksListMob(tasks, TaksBucket.today),
TasksListMob(tasks, TaksBucket.completed),
TasksListMob(tasks, TaksBucket.completed),
TasksListMob(tasks, TaksBucket.archived),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => showAddTaskDialog(context),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
@mkobuolys 解决方案实施后 - 滚动手柄仍然缺失...
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/task.dart';
import '../widgets/tasks_list_mob.dart';
import '../widgets/new_task.dart';
class TaskListName {
final String shortName;
final String longName;
TaskListName(this.shortName, this.longName);
}
class TaksScreen extends StatefulWidget {
@override
_TaksScreenState createState() => _TaksScreenState();
}
class _TaksScreenState extends State with TickerProviderStateMixin {
TabController _tabController;
var _tabIndex = ValueNotifier(2);
final Map tasksListLabels = {
0: TaskListName('Backlog', 'Tasks in backlog'),
1: TaskListName('Tomorrow', 'Planed tasks for tomorrow'),
2: TaskListName('Today', 'Your tasks for today'),
3: TaskListName('Last work day', 'Tasks completed last working day'),
4: TaskListName('Completed', 'Completed Tasks'),
5: TaskListName('Backlog', 'Archived not completed tasks'),
};
@override
void initState() {
super.initState();
_tabController = TabController(length: 6, vsync: this, initialIndex: 2);
}
Future showAddTaskDialog(BuildContext context) async {
await showDialog(
context: context,
builder: (context) => SimpleDialog(
children: [NewTask(TaksBucket.backlog)],
),
);
}
@override
Widget build(BuildContext context) {
final tasks = Provider.of>(context);
return Scaffold(
appBar: AppBar(
title: **ValueListenableBuilder(
valueListenable: _tabIndex,
builder: (context, value, child) =>
Text(tasksListLabels[value].longName),
),**
bottom: TabBar(
controller: _tabController,
isScrollable: true,
onTap: (value) {
_tabIndex.value = _tabController.index;
},
tabs: [
Tab(text: tasksListLabels[0].shortName),
Tab(text: tasksListLabels[1].shortName),
Tab(text: tasksListLabels[2].shortName),
Tab(text: tasksListLabels[3].shortName),
Tab(text: tasksListLabels[4].shortName),
Tab(text: tasksListLabels[5].shortName),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
TasksListMob(tasks, TaksBucket.backlog),
TasksListMob(tasks, TaksBucket.tomorrow),
TasksListMob(tasks, TaksBucket.today),
TasksListMob(tasks, TaksBucket.completed),
TasksListMob(tasks, TaksBucket.completed),
TasksListMob(tasks, TaksBucket.archived),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => showAddTaskDialog(context),
),
);
}
}
最后真的很容易搞定!
我确实创建了 ValueNotifier _tabIndex
在初始状态下,我在 TabControler 上添加了 Listener。 _tabIndex(ValueNotifier) 的侦听器设置值。我确实在 dispose...
中处理了 Listener
在构建方法中将 ValueListenableBuilder 添加到标题。
最终代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/task.dart';
import '../widgets/tasks_list_mob.dart';
import './tasks_notifications_screen.dart';
import '../widgets/new_task.dart';
import '../widgets/count_batch_icon_button.dart';
import '../consts/consts.dart';
import '../util/tasks_helper.dart';
class TaskListName {
final String shortName;
final String longName;
final TaksBucket bucket;
TaskListName(this.shortName, this.longName, this.bucket);
}
class TaksScreen extends StatefulWidget {
@override
_TaksScreenState createState() => _TaksScreenState();
}
class _TaksScreenState extends State with TickerProviderStateMixin {
TabController _tabController;
var _tabIndex = ValueNotifier(2);
final Map tasksListLabels = {
0: TaskListName('Backlog', 'Tasks in backlog', TaksBucket.backlog),
1: TaskListName(
'Tomorrow', 'Planed tasks for tomorrow', TaksBucket.tomorrow),
2: TaskListName('Today', 'Your tasks for today', TaksBucket.today),
3: TaskListName('Last work day', 'Tasks completed last working day',
TaksBucket.completed),
4: TaskListName('Completed', 'Completed Tasks', TaksBucket.completed),
5: TaskListName(
'Archived', 'Archived not completed tasks', TaksBucket.archived),
};
@override
void initState() {
super.initState();
_tabController = TabController(length: 6, vsync: this, initialIndex: 2);
_tabController.addListener(() {
_tabIndex.value = _tabController.index;
});
}
@override
void dispose() {
super.dispose();
_tabController.removeListener(() {
_tabIndex.value = _tabController.index;
});
}
Future showAddTaskDialog(BuildContext context) async {
await showDialog(
context: context,
builder: (context) => SimpleDialog(
children: [NewTask(tasksListLabels[_tabController.index].bucket)],
),
);
}
@override
Widget build(BuildContext context) {
final tasks = Provider.of>(context);
return Scaffold(
appBar: AppBar(
title: ValueListenableBuilder(
valueListenable: _tabIndex,
builder: (context, value, child) =>
Text(tasksListLabels[value].longName),
),
actions: [
CountBatchIconButton(
TasksHelper.numberOfTasksForNotification(tasks),
Icon(Icons.notifications_none),
() => Navigator.of(context).pushNamed(TasksNotifications.routeName),
),
],
bottom: TabBar(
controller: _tabController,
isScrollable: true,
indicatorColor: TaskConsts.mainColor,
tabs: [
Tab(text: tasksListLabels[0].shortName),
Tab(text: tasksListLabels[1].shortName),
Tab(text: tasksListLabels[2].shortName),
Tab(text: tasksListLabels[3].shortName),
Tab(text: tasksListLabels[4].shortName),
Tab(text: tasksListLabels[5].shortName),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
TasksListMob(tasks, TaksBucket.backlog),
TasksListMob(tasks, TaksBucket.tomorrow),
TasksListMob(tasks, TaksBucket.today),
TasksListMob(
tasks,
TaksBucket.completed,
isLastWorkingDay: true,
),
TasksListMob(tasks, TaksBucket.completed),
TasksListMob(tasks, TaksBucket.archived),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: TaskConsts.mainColor,
child: Icon(Icons.add),
onPressed: () => showAddTaskDialog(context),
),
);
}
}
在 TabBar
小部件中,使用 setState
方法添加 onTap
回调以触发重建,从而更新名称:
...
appBar: AppBar(
title: Text(tasksListLabels[_tabController.index].longName),
bottom: TabBar(
controller: _tabController,
isScrollable: true,
tabs: [
Tab(text: tasksListLabels[0].shortName),
Tab(text: tasksListLabels[1].shortName),
Tab(text: tasksListLabels[2].shortName),
Tab(text: tasksListLabels[3].shortName),
Tab(text: tasksListLabels[4].shortName),
Tab(text: tasksListLabels[5].shortName),
],
onTap: (_) {
setState((){});
},
),
),
...
您也可以在列表的帮助下切换标签页时使用相同的文本
您可以使用提供程序 make/view 更改而无需重建整个页面
当我从一个选项卡切换到另一个选项卡时,我想更改 appBar 中的标题。在我当前的代码中不要这样做,因为在更改选项卡上不会调用构建。
感谢大家!!
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/task.dart'; import '../widgets/tasks_list_mob.dart'; import '../widgets/new_task.dart'; class TaskListName { final String shortName; final String longName; TaskListName(this.shortName, this.longName); } class TaksScreen extends StatefulWidget { @override _TaksScreenState createState() => _TaksScreenState(); } class _TaksScreenState extends State with TickerProviderStateMixin { TabController _tabController; final Map tasksListLabels = { 0: TaskListName('Backlog', 'Tasks in backlog'), 1: TaskListName('Tomorrow', 'Planed tasks for tomorrow'), 2: TaskListName('Today', 'Your tasks for today'), 3: TaskListName('Last work day', 'Tasks completed last working day'), 4: TaskListName('Completed', 'Completed Tasks'), 5: TaskListName('Backlog', 'Archived not completed tasks'), }; @override void initState() { super.initState(); _tabController = TabController(length: 6, vsync: this, initialIndex: 2); } @override void dispose() { _tabController.dispose(); super.dispose(); } Future showAddTaskDialog(BuildContext context) async { print(_tabController); await showDialog( context: context, builder: (context) => SimpleDialog( children: [NewTask(TaksBucket.backlog)], ), ); } @override Widget build(BuildContext context) { final tasks = Provider.of>(context); return Scaffold( appBar: AppBar( title: Text(tasksListLabels[_tabController.index].longName), bottom: TabBar( controller: _tabController, isScrollable: true, tabs: [ Tab(text: tasksListLabels[0].shortName), Tab(text: tasksListLabels[1].shortName), Tab(text: tasksListLabels[2].shortName), Tab(text: tasksListLabels[3].shortName), Tab(text: tasksListLabels[4].shortName), Tab(text: tasksListLabels[5].shortName), ], ), ), body: TabBarView( controller: _tabController, children: [ TasksListMob(tasks, TaksBucket.backlog), TasksListMob(tasks, TaksBucket.tomorrow), TasksListMob(tasks, TaksBucket.today), TasksListMob(tasks, TaksBucket.completed), TasksListMob(tasks, TaksBucket.completed), TasksListMob(tasks, TaksBucket.archived), ], ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () => showAddTaskDialog(context), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, ); } }
@mkobuolys 解决方案实施后 - 滚动手柄仍然缺失...
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/task.dart'; import '../widgets/tasks_list_mob.dart'; import '../widgets/new_task.dart'; class TaskListName { final String shortName; final String longName; TaskListName(this.shortName, this.longName); } class TaksScreen extends StatefulWidget { @override _TaksScreenState createState() => _TaksScreenState(); } class _TaksScreenState extends State with TickerProviderStateMixin { TabController _tabController; var _tabIndex = ValueNotifier(2); final Map tasksListLabels = { 0: TaskListName('Backlog', 'Tasks in backlog'), 1: TaskListName('Tomorrow', 'Planed tasks for tomorrow'), 2: TaskListName('Today', 'Your tasks for today'), 3: TaskListName('Last work day', 'Tasks completed last working day'), 4: TaskListName('Completed', 'Completed Tasks'), 5: TaskListName('Backlog', 'Archived not completed tasks'), }; @override void initState() { super.initState(); _tabController = TabController(length: 6, vsync: this, initialIndex: 2); } Future showAddTaskDialog(BuildContext context) async { await showDialog( context: context, builder: (context) => SimpleDialog( children: [NewTask(TaksBucket.backlog)], ), ); } @override Widget build(BuildContext context) { final tasks = Provider.of>(context); return Scaffold( appBar: AppBar( title: **ValueListenableBuilder( valueListenable: _tabIndex, builder: (context, value, child) => Text(tasksListLabels[value].longName), ),** bottom: TabBar( controller: _tabController, isScrollable: true, onTap: (value) { _tabIndex.value = _tabController.index; }, tabs: [ Tab(text: tasksListLabels[0].shortName), Tab(text: tasksListLabels[1].shortName), Tab(text: tasksListLabels[2].shortName), Tab(text: tasksListLabels[3].shortName), Tab(text: tasksListLabels[4].shortName), Tab(text: tasksListLabels[5].shortName), ], ), ), body: TabBarView( controller: _tabController, children: [ TasksListMob(tasks, TaksBucket.backlog), TasksListMob(tasks, TaksBucket.tomorrow), TasksListMob(tasks, TaksBucket.today), TasksListMob(tasks, TaksBucket.completed), TasksListMob(tasks, TaksBucket.completed), TasksListMob(tasks, TaksBucket.archived), ], ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () => showAddTaskDialog(context), ), ); } }
最后真的很容易搞定!
我确实创建了 ValueNotifier _tabIndex
在初始状态下,我在 TabControler 上添加了 Listener。 _tabIndex(ValueNotifier) 的侦听器设置值。我确实在 dispose...
中处理了 Listener在构建方法中将 ValueListenableBuilder 添加到标题。
最终代码:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/task.dart'; import '../widgets/tasks_list_mob.dart'; import './tasks_notifications_screen.dart'; import '../widgets/new_task.dart'; import '../widgets/count_batch_icon_button.dart'; import '../consts/consts.dart'; import '../util/tasks_helper.dart'; class TaskListName { final String shortName; final String longName; final TaksBucket bucket; TaskListName(this.shortName, this.longName, this.bucket); } class TaksScreen extends StatefulWidget { @override _TaksScreenState createState() => _TaksScreenState(); } class _TaksScreenState extends State with TickerProviderStateMixin { TabController _tabController; var _tabIndex = ValueNotifier(2); final Map tasksListLabels = { 0: TaskListName('Backlog', 'Tasks in backlog', TaksBucket.backlog), 1: TaskListName( 'Tomorrow', 'Planed tasks for tomorrow', TaksBucket.tomorrow), 2: TaskListName('Today', 'Your tasks for today', TaksBucket.today), 3: TaskListName('Last work day', 'Tasks completed last working day', TaksBucket.completed), 4: TaskListName('Completed', 'Completed Tasks', TaksBucket.completed), 5: TaskListName( 'Archived', 'Archived not completed tasks', TaksBucket.archived), }; @override void initState() { super.initState(); _tabController = TabController(length: 6, vsync: this, initialIndex: 2); _tabController.addListener(() { _tabIndex.value = _tabController.index; }); } @override void dispose() { super.dispose(); _tabController.removeListener(() { _tabIndex.value = _tabController.index; }); } Future showAddTaskDialog(BuildContext context) async { await showDialog( context: context, builder: (context) => SimpleDialog( children: [NewTask(tasksListLabels[_tabController.index].bucket)], ), ); } @override Widget build(BuildContext context) { final tasks = Provider.of>(context); return Scaffold( appBar: AppBar( title: ValueListenableBuilder( valueListenable: _tabIndex, builder: (context, value, child) => Text(tasksListLabels[value].longName), ), actions: [ CountBatchIconButton( TasksHelper.numberOfTasksForNotification(tasks), Icon(Icons.notifications_none), () => Navigator.of(context).pushNamed(TasksNotifications.routeName), ), ], bottom: TabBar( controller: _tabController, isScrollable: true, indicatorColor: TaskConsts.mainColor, tabs: [ Tab(text: tasksListLabels[0].shortName), Tab(text: tasksListLabels[1].shortName), Tab(text: tasksListLabels[2].shortName), Tab(text: tasksListLabels[3].shortName), Tab(text: tasksListLabels[4].shortName), Tab(text: tasksListLabels[5].shortName), ], ), ), body: TabBarView( controller: _tabController, children: [ TasksListMob(tasks, TaksBucket.backlog), TasksListMob(tasks, TaksBucket.tomorrow), TasksListMob(tasks, TaksBucket.today), TasksListMob( tasks, TaksBucket.completed, isLastWorkingDay: true, ), TasksListMob(tasks, TaksBucket.completed), TasksListMob(tasks, TaksBucket.archived), ], ), floatingActionButton: FloatingActionButton( backgroundColor: TaskConsts.mainColor, child: Icon(Icons.add), onPressed: () => showAddTaskDialog(context), ), ); } }
在 TabBar
小部件中,使用 setState
方法添加 onTap
回调以触发重建,从而更新名称:
...
appBar: AppBar(
title: Text(tasksListLabels[_tabController.index].longName),
bottom: TabBar(
controller: _tabController,
isScrollable: true,
tabs: [
Tab(text: tasksListLabels[0].shortName),
Tab(text: tasksListLabels[1].shortName),
Tab(text: tasksListLabels[2].shortName),
Tab(text: tasksListLabels[3].shortName),
Tab(text: tasksListLabels[4].shortName),
Tab(text: tasksListLabels[5].shortName),
],
onTap: (_) {
setState((){});
},
),
),
...
您也可以在列表的帮助下切换标签页时使用相同的文本
您可以使用提供程序 make/view 更改而无需重建整个页面