Для навигации я создал простой фабричный класс, который генерирует ListTile, который подталкивает маршрут к навигатору:
static Widget simpleNavRow(String text, BuildContext context, String route) {
return Column(
children: <Widget>[
ListTile(
title: Text(text),
onTap: () {
Navigator.pushNamed(context, route);
},
),
Divider(),
],
);
}
Однако вскоре я понял, что было бы удобно поддерживать и push-виджеты (или, если возможно, создавать экземпляры из их класса). Я не мог понять, как заставить аргумент «маршрут» принимать либо строку, либо виджет, поэтому я создал класс, который инициализируется одним из этих двух типов. Этот код работает, но есть ли лучший способ добиться этого?
class NavTo {
String route;
Widget widget;
NavTo.route(this.route);
NavTo.widget(this.widget);
push(BuildContext context) {
if (route != null) {
Navigator.pushNamed(context, route);
}
if (widget != null) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return widget;
}));
}
}
}
class ListHelper {
static final padding = EdgeInsets.all(12.0);
static Widget simpleNavRow(String text, BuildContext context, NavTo navTo) {
return Column(
children: <Widget>[
ListTile(
title: Text(text),
onTap: () {
navTo.push(context);
},
),
Divider(),
],
);
}
}
// usage:
// ListHelper.simpleNavRow('MyWidget', context, NavTo.widget(MyWidget()))
@pskink В этой конкретной реализации я настраиваю игровую площадку в своем проекте для тестирования различных виджетов по мере их создания. У каждого компонента есть свой экран, но он не настолько важен, чтобы он был указан в моем указателе маршрутов. Вот почему я просто хочу запихнуть тупой виджет.

Поскольку вы ожидаете один из нескольких типов, как насчет наличия dynamic, а затем в методе push NavTo, вы можете проверить тип:
class NavTo {
dynamic route;
push(BuildContext context) {
if (route is String) {
...
} else if (route is Widget) {
...
}
}
}
Чтобы расширить мой ответ, вы ищете тип союза. Некоторое исследование привело меня к этому решение от Tobe и эта статья. Надеюсь, они проинформируют вас о ваших дальнейших действиях.
Спасибо. Не знал, как это называется. Поскольку это не поддерживается языком, я, вероятно, просто буду придерживаться текущего решения. Целая библиотека только для этого - это перебор.
Я не верю, что тип профсоюзов доступен в Dart. Мне нравится ваше решение по сравнению с использованием dynamic, поскольку оно строго типизировано. Вы можете использовать именованные параметры.
NavTo({this.route,this.widget})
Но тогда у вас нет проверки типа компиляции для одного-единственного параметра.
Единственное улучшение, которое я бы внес в ваши конструкторы, - это добавить @required.
Лично мне нравится давать Items параметры MaterialPageRoute
static Widget simpleNavRow(String text, BuildContext context, MaterialPageRoute route) {
return Column(
children: <Widget>[
ListTile(
title: Text(text),
onTap: () {
Navigator.push(context, route);
},
),
Divider(),
],);
}
элементы остаются такими же тупыми, и я решаю, что они делают в родительском элементе. После того, как вы сможете создать фабрику элементов для каждого типа, вы инициализируете правильный маршрут следующим образом:
class ItemExemple extends StatelessWidget {
final String text;
final MaterialPageRoute route;
ItemExemple(this.text, this.route);
factory ItemExemple.typeA(String text, BuildContext context) =>
new ItemExemple(text, new MaterialPageRoute(builder: (context) => new ItemA()));
factory ItemExemple.typeB(String text, BuildContext context) =>
new ItemExemple(text, new MaterialPageRoute(builder: (context) => new ItemB()));
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ListTile(
title: Text(this.text),
onTap: () {
Navigator.push(context, route);
},
),
Divider(),
],);
}
}
что насчет
MaterialApp#onGenerateRoute? таким образом вы можете использоватьpushNamedи по-прежнему иметь свободу возвращать любойRoute, какой захотите.