flutter - 在 Flutter CupertinoTabBar + StreamBuilder 中,代码正在运行,但未重建小部件
问题描述
我有一个 2 选项卡屏幕,我想根据用户的交互动态重建内容。在第一个选项卡上,我尝试通过使用模型和提供程序设置当前步骤名称来处理多个状态。对于按下按钮后的第二个屏幕,我在控制台中收到打印消息,但 CupertinoTabView 的内容保持不变。
最小可运行代码片段:
主要.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_app/screens/login.dart';
import 'package:my_app/screens/tab_bar.dart';
import 'package:my_app/models/model.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
return runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => Model(),
),
],
child: CupertinoApp(
theme: const CupertinoThemeData(
brightness: Brightness.light,
scaffoldBackgroundColor: CupertinoColors.white,
),
initialRoute: '/',
routes: {
'/': (context) => LoginScreen(),
'/tab_bar': (context) => TabBarScreen(),
//'/add_item': (context) => AddItemScreen(),
},
),
);
}
}
登录.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_app/models/model.dart';
class LoginScreen extends StatelessWidget {
final model = Model();
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('app',),
),
child: Container(
alignment: FractionalOffset.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
child: Text('next'),
onPressed: (){
model.setStep('step1');
Navigator.pushNamed(context, '/tab_bar');
},
style: ElevatedButton.styleFrom(
primary: CupertinoColors.white,
side: BorderSide(color: Colors.blue, width: 2.0)
),
),
]
),
),
);
}
}
tab_bar.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_app/models/model.dart';
class TabBarScreen extends StatefulWidget {
@override
State createState() => TabBarScreenState();
}
class TabBarScreenState extends State<TabBarScreen> {
final model = Model();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
print(model.getStep);
return Consumer<Model>(
builder: (context, model, _) => CupertinoTabScaffold(
tabBar: CupertinoTabBar(
backgroundColor: CupertinoColors.white,
inactiveColor: Colors.blue,
activeColor: Colors.blueAccent,
border: const Border(
top: BorderSide(
color: CupertinoColors.activeBlue,
width: 2.0,
),
),
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.favorite_outline_outlined),
),
BottomNavigationBarItem(
icon: Icon(Icons.more_vert_sharp),
),
],
),
tabBuilder: (context, index) {
late final CupertinoTabView returnValue;
switch (index) {
case 0:
if (model.getStep == 'step1') {
print('step1');
returnValue = CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: SafeArea(
child: GestureDetector(
onTap: (){ },
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.only(bottom: 15.0),
child: FloatingActionButton(
onPressed: () { model.setStep('step2'); setState(() {
}); },
tooltip: 'step2',
child: Icon(Icons.add),
backgroundColor: CupertinoColors.white,
foregroundColor: CupertinoColors.black,
),
),
],
),
],
),
),
),
);
});
}
else if (model.getStep == 'step2') {
print('step2');
returnValue = CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: SafeArea(
child: Column(
children: <Widget> [
Text('step2'),
],
),
),
);
});
}
else {
returnValue = CupertinoTabView(builder: (context) {
return Container();
});
}
break;
case 1:
returnValue = CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: Text("Tab2"),
);
});
break;
}
return returnValue;
},
),
);
}
}
模型.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Model extends ChangeNotifier {
static String currentStep = 'login';
// login
// step1 - step1
// step2 - step2
String get getStep {
return currentStep;
}
void setStep(String step) {
currentStep = step;
notifyListeners();
}
}
我希望在按下 step1 中的按钮以显示 step2 内容时重建选项卡。在控制台中,按下时我可以看到“step2”的打印,但实际选项卡保持不变。感谢你的帮助
解决方案
由于没有人回答,我自己想通了。解决方法是像这样使用 Navigator:
onPressed: () {
Navigator.of(context).push(
CupertinoPageRoute<void>(
builder: (BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Page 2 of tab'),
),
child: Center(
child: CupertinoButton(
child: const Text('Back'),
onPressed: () { Navigator.of(context).pop(); },
),
),
);
},
),
);
},
因此您不需要“else if”调节。
推荐阅读
- spring - Spring Cloud Dataflow - 并行任务
- java - 使用泛型从具有公共父类的类的单一实现中继承
- java - 在 Gitlab-CI(maven 和 java)中运行 selenium 测试
- javascript - express/node 中带下划线的命令
- javascript - NodeJS:承诺没有回应
- c# - ViewDataDictionary 模型类型异常
- windows - 如何检查WMIC是否输出空字符串或请求的Windows原始产品密钥?
- sage - 用矩阵组合集合:sagemath
- spring-webflux - 使用spring响应式webClient面临问题“WebClientRequestException:挂起的获取队列已达到其最大大小1000”
- php - 重定向和 reauth=1 的奇怪 wp-admin 登录问题