Flutter:Hero widget、Navigation 2.0 和 Provider 不能一起正常工作
Flutter: Hero widget, Navigation 2.0 and Provider are not working properly together
我尝试将 Hero
小部件与 ChangeNotifierProvider
和新的 Navigation 2.0 系统一起使用。但我在那里面临问题。当不使用 changeNotifier
时,相同的代码 有效 。
我遇到的问题是,弹出第二页W2后,第一页的文字(即英雄的child)消失了。
完整代码如下。 runApp(HeroTestApp2())
照常工作。但我很想让第一种方法起作用。请帮忙。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
main(List<String> args) {
runApp(HeroTestApp());
}
class MyModel extends ChangeNotifier {
bool _go = false;
bool get go => _go;
set go(bool go) {
_go = go;
notifyListeners();
}
}
class HeroTestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
create: (context) => MyModel(),
builder: (context, _) {
final state = context.watch<MyModel>();
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(child: W1(onTapped: null)),
if (state.go) MaterialPage(child: W2()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
state.go = false;
return true;
},
observers: [HeroController()],
),
);
},
);
}
}
class HeroTestApp2 extends StatefulWidget {
@override
_HeroTestApp2State createState() => _HeroTestApp2State();
}
class _HeroTestApp2State extends State<HeroTestApp2> {
bool go = false;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(
child: W1(onTapped: () {
setState(() {
go = true;
});
}),
),
if (go) MaterialPage(child: W2()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
go = false;
return true;
},
observers: [HeroController()],
),
);
}
}
class W1 extends StatelessWidget {
final void Function() onTapped;
const W1({Key key, this.onTapped}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTapped ??
() => context.read<MyModel>().go = true,
child: Scaffold(
appBar: AppBar(),
body: Container(
alignment: Alignment.topRight,
child: Hero(
tag: "topic",
child: DefaultTextStyle(
style: TextStyle(
fontSize: 40,
decoration: TextDecoration.none,
color: Colors.blue),
child: Text(
"data",
style: TextStyle(fontSize: 40),
),
),
),
),
),
);
}
}
class W2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
alignment: Alignment.bottomLeft,
child: Hero(
tag: "topic",
child: DefaultTextStyle(
style: TextStyle(
fontSize: 140,
decoration: TextDecoration.none,
color: Colors.blue),
child: Text(
"data",
),
),
),
),
);
}
}
好的,找到答案了
这是observers: [HeroController()],
每次状态发生变化时,洞树都会与 HeroController 一起重建。解决办法是在changeNotifier上面定义HeroController:
class HeroTestApp extends StatelessWidget {
final heroC = HeroController();
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
create: (context) => MyModel(),
builder: (context, _) {
final state = context.watch<MyModel>();
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(child: W1(onTapped: null)),
if (state.go) MaterialPage(child: W2()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
state.go = false;
return true;
},
observers: [heroC],
),
);
},
);
}
}
谢谢。
我尝试将 Hero
小部件与 ChangeNotifierProvider
和新的 Navigation 2.0 系统一起使用。但我在那里面临问题。当不使用 changeNotifier
时,相同的代码 有效 。
我遇到的问题是,弹出第二页W2后,第一页的文字(即英雄的child)消失了。
完整代码如下。 runApp(HeroTestApp2())
照常工作。但我很想让第一种方法起作用。请帮忙。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
main(List<String> args) {
runApp(HeroTestApp());
}
class MyModel extends ChangeNotifier {
bool _go = false;
bool get go => _go;
set go(bool go) {
_go = go;
notifyListeners();
}
}
class HeroTestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
create: (context) => MyModel(),
builder: (context, _) {
final state = context.watch<MyModel>();
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(child: W1(onTapped: null)),
if (state.go) MaterialPage(child: W2()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
state.go = false;
return true;
},
observers: [HeroController()],
),
);
},
);
}
}
class HeroTestApp2 extends StatefulWidget {
@override
_HeroTestApp2State createState() => _HeroTestApp2State();
}
class _HeroTestApp2State extends State<HeroTestApp2> {
bool go = false;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(
child: W1(onTapped: () {
setState(() {
go = true;
});
}),
),
if (go) MaterialPage(child: W2()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
go = false;
return true;
},
observers: [HeroController()],
),
);
}
}
class W1 extends StatelessWidget {
final void Function() onTapped;
const W1({Key key, this.onTapped}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTapped ??
() => context.read<MyModel>().go = true,
child: Scaffold(
appBar: AppBar(),
body: Container(
alignment: Alignment.topRight,
child: Hero(
tag: "topic",
child: DefaultTextStyle(
style: TextStyle(
fontSize: 40,
decoration: TextDecoration.none,
color: Colors.blue),
child: Text(
"data",
style: TextStyle(fontSize: 40),
),
),
),
),
),
);
}
}
class W2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
alignment: Alignment.bottomLeft,
child: Hero(
tag: "topic",
child: DefaultTextStyle(
style: TextStyle(
fontSize: 140,
decoration: TextDecoration.none,
color: Colors.blue),
child: Text(
"data",
),
),
),
),
);
}
}
好的,找到答案了
这是observers: [HeroController()],
每次状态发生变化时,洞树都会与 HeroController 一起重建。解决办法是在changeNotifier上面定义HeroController:
class HeroTestApp extends StatelessWidget {
final heroC = HeroController();
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
create: (context) => MyModel(),
builder: (context, _) {
final state = context.watch<MyModel>();
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(child: W1(onTapped: null)),
if (state.go) MaterialPage(child: W2()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
state.go = false;
return true;
},
observers: [heroC],
),
);
},
);
}
}
谢谢。