Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Routing 带颤振的嵌套路径_Routing_Dart_Flutter - Fatal编程技术网

Routing 带颤振的嵌套路径

Routing 带颤振的嵌套路径,routing,dart,flutter,Routing,Dart,Flutter,我正试图为以下问题找到良好的体系结构解决方案:我有以下一级路线,也可以称为布局: 根据用户的身份验证状态、操作等,用户将被路由到其中的每一个。。我正确地理解了这个阶段 例如,当我想使用可称为页面的二级路由时,会出现问题 /onboarding/signin -> Shows onboarding layout, that displays signin route /onboarding/plan -> Shows onboarding layout, that displays p

我正试图为以下问题找到良好的体系结构解决方案:我有以下一级路线,也可以称为布局:

根据用户的身份验证状态、操作等,用户将被路由到其中的每一个。。我正确地理解了这个阶段

例如,当我想使用可称为页面的二级路由时,会出现问题

/onboarding/signin -> Shows onboarding layout, that displays signin route
/onboarding/plan -> Shows onboarding layout, that displays plan options
/modal/plan-info -> Shows modal layout, over previous page (/onboarding/plan) and displays plan-information page.
我如何才能最好地定义/组织这些内容,以便有效地将其发送到布局和显示的页面?请注意,每当我在一个布局中路由页面时,布局不会改变,但我希望根据路由设置其内部正在改变的内容(页面)的动画

到目前为止,我取得了以下成就

import "package:flutter/widgets.dart";
import "package:skimitar/layouts/Onboarding.dart";
import "package:skimitar/layouts/Dashboard.dart";

Route generate(RouteSettings settings) {
  Route page;
  switch (settings.name) {
    case "/onboarding":
      page = new PageRouteBuilder(pageBuilder: (BuildContext context,
          Animation<double> animation, Animation<double> secondaryAnimation) {
        return new Onboarding();
      });
      break;
      case "/dashboard":
      page = new PageRouteBuilder(pageBuilder: (BuildContext context,
          Animation<double> animation, Animation<double> secondaryAnimation) {
        return new Dashboard();
      });
      break;
  }
  return page;
}

/* Main */
void main() {
  runApp(new WidgetsApp(
      onGenerateRoute: generate, color: const Color(0xFFFFFFFFF)));
}
入职。dart

import "package:flutter/widgets.dart";
import "package:myProject/containers/layouts/Onboarding.dart";

/* Main */
void main() {
  runApp(new Onboarding());
}
import "package:flutter/widgets.dart";
import "package:myProject/containers/pages/SignIn.dart";
import "package:myProject/containers/pages/SignUp.dart";
import "package:myProject/services/helpers.dart";

/* Onboarding router */
Route onboardingRouter(RouteSettings settings) {
  Route page;
  switch (settings.name) {
    case "/":
      page = buildOnboardingRoute(new SignIn());
      break;
    case "/sign-up":
      page = buildOnboardingRoute(new SignUp());
      break;
    default:
      page = buildOnboardingRoute(new SignIn());
  }
  return page;
}

class Onboarding extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      decoration: new BoxDecoration(
          color: const Color(0xFF000000),
          image: new DecorationImage(
              image: new AssetImage("assets/images/background-fire.jpg"),
              fit: BoxFit.cover)),
      child: new WidgetsApp(
          onGenerateRoute: onboardingRouter, color: const Color(0xFF000000)),
    );
  }
}
import "package:flutter/widgets.dart";

class SignUp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Center(
        child: new Text("Sign Up",
            style: new TextStyle(color: const Color(0xFFFFFFFF))));
  }
}
import "package:flutter/widgets.dart";

Route buildOnboardingRoute(Widget page) {
  return new PageRouteBuilder(
      opaque: true,
      pageBuilder: (BuildContext context, _, __) {
        return page;
      });
}
注册。省道

import "package:flutter/widgets.dart";
import "package:myProject/containers/layouts/Onboarding.dart";

/* Main */
void main() {
  runApp(new Onboarding());
}
import "package:flutter/widgets.dart";
import "package:myProject/containers/pages/SignIn.dart";
import "package:myProject/containers/pages/SignUp.dart";
import "package:myProject/services/helpers.dart";

/* Onboarding router */
Route onboardingRouter(RouteSettings settings) {
  Route page;
  switch (settings.name) {
    case "/":
      page = buildOnboardingRoute(new SignIn());
      break;
    case "/sign-up":
      page = buildOnboardingRoute(new SignUp());
      break;
    default:
      page = buildOnboardingRoute(new SignIn());
  }
  return page;
}

class Onboarding extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      decoration: new BoxDecoration(
          color: const Color(0xFF000000),
          image: new DecorationImage(
              image: new AssetImage("assets/images/background-fire.jpg"),
              fit: BoxFit.cover)),
      child: new WidgetsApp(
          onGenerateRoute: onboardingRouter, color: const Color(0xFF000000)),
    );
  }
}
import "package:flutter/widgets.dart";

class SignUp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Center(
        child: new Text("Sign Up",
            style: new TextStyle(color: const Color(0xFFFFFFFF))));
  }
}
import "package:flutter/widgets.dart";

Route buildOnboardingRoute(Widget page) {
  return new PageRouteBuilder(
      opaque: true,
      pageBuilder: (BuildContext context, _, __) {
        return page;
      });
}
助手。省道

import "package:flutter/widgets.dart";
import "package:myProject/containers/layouts/Onboarding.dart";

/* Main */
void main() {
  runApp(new Onboarding());
}
import "package:flutter/widgets.dart";
import "package:myProject/containers/pages/SignIn.dart";
import "package:myProject/containers/pages/SignUp.dart";
import "package:myProject/services/helpers.dart";

/* Onboarding router */
Route onboardingRouter(RouteSettings settings) {
  Route page;
  switch (settings.name) {
    case "/":
      page = buildOnboardingRoute(new SignIn());
      break;
    case "/sign-up":
      page = buildOnboardingRoute(new SignUp());
      break;
    default:
      page = buildOnboardingRoute(new SignIn());
  }
  return page;
}

class Onboarding extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      decoration: new BoxDecoration(
          color: const Color(0xFF000000),
          image: new DecorationImage(
              image: new AssetImage("assets/images/background-fire.jpg"),
              fit: BoxFit.cover)),
      child: new WidgetsApp(
          onGenerateRoute: onboardingRouter, color: const Color(0xFF000000)),
    );
  }
}
import "package:flutter/widgets.dart";

class SignUp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Center(
        child: new Text("Sign Up",
            style: new TextStyle(color: const Color(0xFFFFFFFF))));
  }
}
import "package:flutter/widgets.dart";

Route buildOnboardingRoute(Widget page) {
  return new PageRouteBuilder(
      opaque: true,
      pageBuilder: (BuildContext context, _, __) {
        return page;
      });
}
您试图构建的模式,即使是合理的,似乎也无法用flatter直接表示出来

编辑:您想要实现的行为需要使用onGenerateRoute,但尚未(2018年1月)正确记录()。请参见@Darky answer以获得示例。他提出了
NestedRouteBuilder
NestedRoute
实现,填补了这一空白

使用MaterialApp中的普通导航器,路由和页面导航(根据)有两个主要特征,它们否定了您想要实现的目标(至少是直接实现的)。一方面,
Navigator
表现为一个堆栈,从而将一条路由推到下一条路由之上,以此类推,另一条路由要么是全屏路由,要么是模式路由,这意味着它们占据了部分屏幕,但它们抑制了与下方小部件的交互。更明确地说,您的范例似乎需要在堆栈中的不同的级别上与页面同时交互-这不能用这种方式完成

此外,它感觉路径范式不仅仅是一个层次-一般框架→ 特定子页面-但首先是导航器中堆栈的表示形式。我自己也被骗了,但我明白了:

String initialRoute

final

要显示的第一条管线的名称

默认情况下,这遵从dart:ui.Window.defaultRouteName

如果此字符串包含任何/个字符,则该字符串在 从字符串开始到结束的那些字符和子字符串 每一个这样的字符依次用作推送的路径

例如,如果使用route/stocks/HOOLI作为初始路由, 然后导航器将在启动时推送以下路由:/, /股票,/股票/胡利。这将启用深度链接,同时允许 用于维护可预测路线历史记录的应用程序

一种可能的解决方法,如下所示,是利用路径名实例化子窗口小部件,保留一个状态变量以知道显示什么:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new ActionPage(title: 'Flutter Demo Home Page'),
      routes: <String, WidgetBuilder>{
        '/action/plus': (BuildContext context) => new ActionPage(sub: 'plus'),
        '/action/minus': (BuildContext context) => new ActionPage(sub: 'minus'),
      },
    );
  }
}

class ActionPage extends StatefulWidget {
  ActionPage({Key key, this.title, this.sub = 'plus'}) : super(key: key);

  final String title, sub;

  int counter;

  final Map<String, dynamic> subroutes = {
    'plus': (BuildContext context, int count, dynamic setCount) =>
        new PlusSubPage(count, setCount),
    'minus': (BuildContext context, int count, dynamic setCount) =>
        new MinusSubPage(count, setCount),
  };

  @override
  ActionPageState createState() => new ActionPageState();
}

class ActionPageState extends State<ActionPage> {
  int _main_counter = 0;

  String subPageState;

  @override
  void initState() {
    super.initState();
    subPageState = widget.sub;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('Testing subpages'),
          actions: <Widget>[
            new FlatButton(
                child: new Text('+1'),
                onPressed: () {
                  if (subPageState != 'plus') {
                    setState(() => subPageState = 'plus');
                    setState(() => null);
                  }
                }),
            new FlatButton(
                child: new Text('-1'),
                onPressed: () {
                  if (subPageState != 'minus') {
                    setState(() => subPageState = 'minus');
                    setState(() => null);
                  }
                }),
          ],
        ),
        body: widget.subroutes[subPageState](context, _main_counter, (count) {
          _main_counter = count;
        }));
  }
}

class PlusSubPage extends StatefulWidget {
  PlusSubPage(this.counter, this.setCount);
  final setCount;
  final int counter;
  @override
  _PlusSubPageState createState() => new _PlusSubPageState();
}

class _PlusSubPageState extends State<PlusSubPage> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();
    _counter = widget.counter;
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
      widget.setCount(_counter);
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new IconButton(
            icon: const Icon(Icons.add),
            onPressed: _incrementCounter,
          ),
          new Text(
            'You have pushed the button this many times:',
          ),
          new Text(
            '$_counter',
            style: Theme.of(context).textTheme.display1,
          ),
        ],
      ),
    );
  }
}

class MinusSubPage extends StatefulWidget {
  MinusSubPage(this.counter, this.setCount);
  final setCount;
  final int counter;
  @override
  _MinusSubPageState createState() => new _MinusSubPageState();
}

class _MinusSubPageState extends State<MinusSubPage> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();
    _counter = widget.counter;
  }

  void _decrementCounter() {
    setState(() {
      _counter--;
      widget.setCount(_counter);
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new IconButton(
            icon: const Icon(Icons.remove),
            onPressed: _decrementCounter,
          ),
          new Text(
            'You have pushed the button this many times:',
          ),
          new Text(
            '$_counter',
            style: Theme.of(context).textTheme.display1,
          ),
        ],
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(新的MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回新材料PP(
标题:“颤振演示”,
主题:新主题数据(
主样本:颜色。蓝色,
),
主页:新的ActionPage(标题:“颤振演示主页”),
路线:{
“/action/plus”:(BuildContext上下文)=>newactionPage(sub:'plus'),
“/action/minus”:(BuildContext上下文)=>newactionPage(sub:'minus'),
},
);
}
}
类ActionPage扩展StatefulWidget{
ActionPage({Key-Key,this.title,this.sub='plus'}):super(Key:Key);
最终字符串标题,子字符串;
整数计数器;
最终映射子例程={
“plus”:(BuildContext上下文、int计数、动态setCount)=>
新PlusSubPage(计数,设置计数),
“减”:(BuildContext上下文、int计数、动态setCount)=>
新的子页面(计数,设置计数),
};
@凌驾
ActionPageState createState()=>新建ActionPageState();
}

类ActionPageState扩展了状态动画,它们可以为您提供在视图之间寻找的连续性。

虽然从技术上讲可以嵌套“Navigator”,但这里不推荐这种做法(因为它破坏了英雄动画)

您可以使用
onGenerateRoute
构建嵌套的“路由”,在路由“/dashboard/profile”的情况下,构建树
WidgetApp>dashboard>profile
。我想这就是你想要实现的

结合一个高阶函数,您可以为自己创建
onGenerateRoute

为了提供代码流的线索:
NestedRoute
忽略了布局的精确构建,让它进入
builder
方法(例如
builder:(child)=>新仪表板(child:child),
)。调用
buildRoute
方法时,我们将为此页面的实例生成一个
PageRouteBuilder
,但是让
\u build
管理
小部件的创建。在
\u build
中,我们要么按原样使用
生成器
,要么让它调用请求的子例程,调用自己的
\u build
来膨胀子例程。完成后,我们将使用构建的子例程作为构建器的参数。长话短说,您递归地深入到进一步的路径级别,以构建路由的最后一个级别,然后让它从递归中上升,并将结果用作外部级别的参数,依此类推

BuildNestedRoutes
为您执行脏工作,并解析
NestedRoutes
列表,以构建必要的
路由设置

下面的例子

例如:

@override
Widget build(BuildContext context) {
  return new MaterialApp(
    initialRoute: '/foo/bar',
    home: const FooBar(),
    onGenerateRoute: buildNestedRoutes(
      [
        new NestedRoute(
          name: 'foo',
          builder: (child) => new Center(child: child),
          subRoutes: [
            new NestedRoute(
              name: 'bar',
              builder: (_) => const Text('bar'),
            ),
            new NestedRoute(
              name: 'baz',
              builder: (_) => const Text('baz'),
            )
          ],
        ),
      ],
    ),
  );
}
在这里,您只需定义嵌套路由(名称+关联组件)。 和
NestedRoute
class+
buildNestedRoutes
方法定义如下:

typedef Widget NestedRouteBuilder(Widget child);

@immutable
class NestedRoute {
  final String name;
  final List<NestedRoute> subRoutes;
  final NestedRouteBuilder builder;

  const NestedRoute({@required this.name, this.subRoutes, @required this.builder});

  Route buildRoute(List<String> paths, int index) {
    return new PageRouteBuilder<dynamic>(
      pageBuilder: (_, __, ___) => _build(paths, index),
    );
  }

  Widget _build(List<String> paths, int index) {
    if (index > paths.length) {
      return builder(null);
    }
    final route = subRoutes?.firstWhere((route) => route.name == paths[index], orElse: () => null);
    return builder(route?._build(paths, index + 1));
  }
}

RouteFactory buildNestedRoutes(List<NestedRoute> routes) {
  return (RouteSettings settings) {
    final paths = settings.name.split('/');
    if (paths.length <= 1) {
      return null;
    }
    final rootRoute = routes.firstWhere((route) => route.name == paths[1]);
    return rootRoute.buildRoute(paths, 2);
  };
}
typedef小部件NestedRouteBuilder(小部件子部件);
@不变的