我是Flutter的新手。
我有一个带有2个子小部件的应用程序(Android中有2个片段),当我点击WidgetA中的下一个按钮时,我想将该小部件替换(或推送)到WidgetChildA中,就像在Android中推送(或替换)片段一样。但不是那样,我在Flutter中得到了一个像普通屏幕一样的全屏小部件。
这是我的代码:
import 'package:flutter/material.dart';
class DemoFragment extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new DemoFragmentState();
}
}
class DemoFragmentState extends State<DemoFragment> {
@override
Widget build(BuildContext context) {
print(context.toString() + context.hashCode.toString());
return new Scaffold(
appBar: new AppBar(title: new Text("Demo fragment")),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new FragmentA(),
new FragmentB()
],
),
);
}
}
class FragmentA extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(context.toString() + context.hashCode.toString());
return new Center(
child: new Column(
children: <Widget>[
new Text("Fragment A"),
new RaisedButton(
child: new Text("next"),
onPressed: () {
print(context.toString() + context.hashCode.toString());
Navigator.of(context).push(new PageRouteBuilder(
opaque: true,
transitionDuration: const Duration(milliseconds: 0),
pageBuilder: (BuildContext context, _, __) {
return new FragmentChildA();
}));
/*showDialog(
context: context,
builder: (_) => new AlertDialog(
title: new Text("Hello world"),
content: new Text("this is my content"),
));*/
})
],
),
);
}
}
class FragmentB extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(context.toString() + context.hashCode.toString());
return new Center(
child: new Column(
children: <Widget>[
new Text("Fragment B"),
new RaisedButton(
child: new Text("next"),
onPressed: () {
print(context.toString() + context.hashCode.toString());
Navigator.of(context).push(new PageRouteBuilder(
opaque: true,
transitionDuration: const Duration(milliseconds: 0),
pageBuilder: (BuildContext context, _, __) {
return new FragmentChildB();
}));
})
],
));
}
}
class FragmentChildA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[new Text("Fragment Child A")],
)));
}
}
class FragmentChildB extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[new Text("Fragment Child B")],
)));
}
}
截图:
答案 0 :(得分:2)
好吧,我将使用谷歌在底部导航栏上执行此操作的方式进行此操作,但我认为这不是最有效的方法,但是它可以正常工作
class MainFabContainer extends StatefulWidget {
MainFabContainer({
Key key,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return MainFabContainerState();
}
}
class MainFabContainerState extends State<MainFabContainer> {
String title = "Title";
int _currentIndex = 0;
final List<int> _backstack = [0];
@override
Widget build(BuildContext context) {
//each fragment is just a widget which we pass the navigate function
List<Widget> _fragments =[Fragment1(navigate: navigateTo),Fragment2(navigate: navigateTo,),Fragment3(navigate: navigateTo,)];
//will pop scope catches the back button presses
return WillPopScope(
onWillPop: () {
customPop(context);
},
child: Scaffold(
drawer: drawer(),
appBar: AppBar(
title: Text(title),
),
body: Column(
children: <Widget>[
Expanded(
child: _fragments[_currentIndex],
),
],
),
),
);
}
void navigateTo(int index) {
_backstack.add(index);
setState(() {
_currentIndex = index;
});
}
void navigateBack(int index) {
setState(() {
_currentIndex = index;
});
}
customPop(BuildContext context) {
if (_backstack.length - 1 > 0) {
navigateBack(_backstack[_backstack.length - 1]);
} else {
_backstack.removeAt(_backstack.length - 1);
Navigator.pop(context);
}
}
//this method could be called by the navigate and navigate back methods
_setTitle(String appBarTitle) {
setState(() {
title = appBarTitle;
});
}
}
答案 1 :(得分:1)
我不确定你是否可以使用路由器来替换视图的一部分;但您可以有条件地更改在构建方法中呈现的窗口小部件,如下所示:
children: <Widget>[
someCondition ? new FragmentA() : new FragmentChildA(),
new FragmentB()
],
然后您只需要在有状态小部件中使用someCondition
设置setState
:
setState(() => someCondition = true);
如果你想从FragmentA
内部执行此操作,可以允许它将函数传递给它的构造函数:
new FragmentA(
onPress: setState(() => someCondition = true)
)
但是,最好将所有这些逻辑封装在一个小部件中,这样这个逻辑就不会在父级中徘徊。您可以为FragementA创建一个StatefulWidget
,它会跟踪您所处的阶段,然后在其构建方法中呈现正确的子窗口小部件,如:
build() {
switch(stage) {
Stages.Stage1:
return new Stage1(
onNext: () => setState(() => stage = Stages.Stage2);
);
Stages.Stage2:
return new Stage1(
onPrevious: () => setState(() => stage = Stages.Stage1);
);
}
}
答案 2 :(得分:0)
您可以简单地将MaterialApp小部件与CupertinoPageTransitionsBuilder一起用作pageTransitionTheme,例如
MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(builders: {
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
TargetPlatform.android: SlideRightPageTransitionsBuilder(),
}),
initialRoute: "fragment1",
routes: <String, WidgetBuilder>{
"fragment1": (BuildContext context) => Fragment1(),
"fragment2": (BuildContext context) => Fragment2(),
}
...
),
然后在片段1中,您只需使用以下内容即可通过幻灯片动画导航到另一个片段
Navigator.of(context).pushReplacementNamed("fragment2");
答案 3 :(得分:-1)
简单地使用SingleStatefull小部件,然后在创建状态中进行一些布尔运算,以调用不同的状态小部件来充当fragment。 例如
if(showUpload)
{
return new _Upload(responseUpload: response); // Fragment 1
}else
{
return EditState(mapSaved: map,); // Fragment 2
}