在 Flutter 中替换片段之类的小部件

Châ*_*húc 11 android dart flutter

我是 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")],
    )));
  }
}
Run Code Online (Sandbox Code Playgroud)

截图:

主页
在此处输入图片说明

点击后
在此处输入图片说明

Dan*_*eny 5

我不确定您是否可以使用路由器来替换视图的一部分;但是您可以有条件地更改您在构建方法中呈现的 Widget,如下所示:

children: <Widget>[
    someCondition ? new FragmentA() : new FragmentChildA(),
    new FragmentB()
],
Run Code Online (Sandbox Code Playgroud)

然后你只需要在有状态小部件中someCondition使用设置setState

setState(() => someCondition = true);
Run Code Online (Sandbox Code Playgroud)

如果您想从内部执行此操作,FragmentA您可以允许它将该函数传递给其构造函数:

new FragmentA(
  onPress: setState(() => someCondition = true)
)
Run Code Online (Sandbox Code Playgroud)

但是,最好将所有这些逻辑封装在一个小部件中,这样该逻辑就不会全部挂在父级中。您可以StatefulWidget为 FragmentA制作一个单曲,它跟踪您所在的阶段,然后在其构建方法中呈现正确的子小部件,例如:

build() {
  switch(stage) {
    Stages.Stage1:
      return new Stage1(
        onNext: () => setState(() => stage = Stages.Stage2);
      );
    Stages.Stage2:
      return new Stage1(
        onPrevious: () => setState(() => stage = Stages.Stage1);
      );
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以简单地使用带有 CupertinoPageTransitionsBuilder 作为 pageTransitionTheme 的 MaterialApp 小部件,例如

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(),
   }
...
),
Run Code Online (Sandbox Code Playgroud)

然后在片段 1 中,您只需使用以下内容通过幻灯片动画导航到另一个片段

Navigator.of(context).pushReplacementNamed("fragment2");
Run Code Online (Sandbox Code Playgroud)


Châ*_*húc 4

好吧,我几个月前就找到了处理这个案子的方法,但我就是忘了回答这个问题。

解决方案是用新的导航器包装您的小部件。

您可以在此处查看视频示例

以及这里的简单演示

该解决方案的缺点是有时键盘没有按照我的意图显示。

  • 我想推荐将代码解决方案放在此处。而不是仅链接到外部资源。 (2认同)