简体   繁体   English

在 Flutter 中,如何使用户选择的下拉菜单选项指向特定的路由?

[英]In Flutter, how to make a user selected dropdown menu option leads to a specific route?

New coder here that's self-taught, so I apologize in advance if my questions is confusing or does not use the right coding terms.这里的新编码员是自学的,所以如果我的问题令人困惑或没有使用正确的编码术语,我提前道歉。

I am trying to create a practice app on flutter, user can select different aspect of the game they like and the app will suggest a game that suit them.我正在尝试在 flutter 上创建一个练习应用程序,用户可以 select 他们喜欢的游戏的不同方面,该应用程序会建议适合他们的游戏。

For the purpose of this app, I will have like 10 games pre-selected to suggest to users.出于这个应用程序的目的,我将预先选择 10 款游戏来推荐给用户。

I have 2 dropdown widget: Genre and difficulty.我有 2 个下拉小部件:类型和难度。

Here is my code:这是我的代码:

//dropdown menu for game genre

class DropDown1Widget extends StatefulWidget {
  DropDown1Widget({Key key}) : super(key: key);

  @override
  _DropDown1WidgetState createState() => _DropDown1WidgetState();
}

class _DropDown1WidgetState extends State<DropDown1Widget> {
  String dropdownValue = 'RPG';

  @override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: dropdownValue,
      icon: Icon(Icons.arrow_drop_down),
      iconSize: 24,
      elevation: 16,
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.deepPurple),
      underline: Container(
        height: 2,
        color: Colors.deepPurpleAccent,
      ),
      onChanged: (String newValue) {
        setState(() {
          dropdownValue = newValue;
        });
      },
      items: <String>[
        'RPG',
        'Shooting',
        'Sport',
        'Racing',
        'Random!'
      ].map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
    );
  }
}

//Drop down menu 2 for difficulty level
class DropDown2Widget extends StatefulWidget {
  DropDown2Widget({Key key}) : super(key: key);

  @override
  _DropDown2WidgetState createState() => _DropDown2WidgetState();
}

class _DropDown2WidgetState extends State<DropDown2Widget> {
  String dropdownValue = 'Hard';

  @override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: dropdownValue,
      icon: Icon(Icons.arrow_drop_down),
      iconSize: 24,
      elevation: 16,
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.pink),
      underline: Container(
        height: 2,
        color: Colors.pinkAccent,
      ),
      onChanged: (String newValue) {
        setState(() {
          dropdownValue = newValue;
        });
      },
      items: <String>['Hard', 'Intermediate', 'Easy', 'Random!']
          .map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
    );
  }
}

So far I just have these 2 dropdownmenu widgets placed in one of my routes, but I would like for it to lead to a specific route when user select a specific combination of the dropdown menus and press submit.到目前为止,我只是将这 2 个下拉菜单小部件放置在我的一条路线中,但我希望它在用户 select 下拉菜单的特定组合并按提交时引导到特定路线。

For example, if an user selects genre: RPG, difficulty level: Hard, and presses "submit" (I also have a onPress button waiting to take the user to the specific route), it would take them to a route that shows "Dark Soul 2".例如,如果用户选择类型:RPG,难度级别:Hard,然后按“提交”(我还有一个 onPress 按钮等待将用户带到特定路线),它会将他们带到显示“黑暗灵魂 2"。

I am guessing I have to do some if-else codes, but i am not sure how to implement it.我猜我必须做一些 if-else 代码,但我不确定如何实现它。

Also, if user select "Random" for the dropdownmenu, how do i implement random selection of the routes that the app leads to?此外,如果用户 select 为下拉菜单“随机”,我如何实现应用程序引导的路由的随机选择?

Sorry for the wordy question, still have a lot to learn.抱歉这个冗长的问题,还有很多东西要学。

You can handle the route navigation using any package or a basic onGenerateRoute() .您可以使用任何 package 或基本的onGenerateRoute()来处理路线导航。 Here I have used a quick hack to show the concept, which is an example of how not to do things.在这里,我使用了一个快速的技巧来展示这个概念,这是一个如何不做事的例子。 So, replace route generation logic with more robust code.因此,用更健壮的代码替换路由生成逻辑。


main() async {
  runApp(MyApp());
}

String makeGenreLevelName(Genre genre, DifficultyLevel level) => '${describeEnum(genre)}_${describeEnum(level)}';

Map<String, Widget Function(BuildContext)> routes;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    if (routes == null) {
      routes = {'/': (context) => SO()}; //HACK
      Genre.values.forEach(
        (g) {
          DifficultyLevel.values.forEach(
            (l) {
              routes[makeGenreLevelName(g, l)] = (context) => //
                  Scaffold(appBar: AppBar(title: Text(makeGenreLevelName(g, l))));
            },
          );
        },
      );
    }

    return MaterialApp(
      routes: routes, //use onGenerateRoute or any other logic instead of HACK
      initialRoute: '/',
    );
  }
}

class SO extends StatelessWidget {
  Genre selectedGenre = Genre.Random;
  DifficultyLevel selectedDiffLevel = DifficultyLevel.Random;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: IntrinsicWidth(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              GenreDDWidget(
                initial: selectedGenre,
                onItemChange: (Genre g) => selectedGenre = g,
              ),
              LevelDDWidget(
                initial: selectedDiffLevel,
                onItemChange: (DifficultyLevel d) => selectedDiffLevel = d,
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          print('-' * 20);
          print('Selected Genre: $selectedGenre');
          print('Selected Level: $selectedDiffLevel');

          var playGenre = selectedGenre;
          var playLevel = selectedDiffLevel;

          assert(!(Genre.values.length == 1 && Genre.values.first == Genre.Random));
          assert(!(DifficultyLevel.values.length == 1 && DifficultyLevel.values.first == DifficultyLevel.Random));

          while (playGenre == Genre.Random) playGenre = (Genre.values.toList()..shuffle()).first;
          while (playLevel == DifficultyLevel.Random) playLevel = (DifficultyLevel.values.toList()..shuffle()).first;

          // the genre and the level for upcoming game in the next screen
          print('Upcoming Game Genre: $playGenre');
          print('Upcoming Game Level: $playLevel');
          Navigator.pushNamed(context, makeGenreLevelName(playGenre, playLevel));
        },
      ),
    );
  }
}

class GenreDDWidget extends StatefulWidget {
  final Function(Genre) onItemChange;
  final Genre initial;

  GenreDDWidget({Key key, this.onItemChange, this.initial}) : super(key: key);

  @override
  _GenreDDWidgetState createState() => _GenreDDWidgetState(initial);
}

class _GenreDDWidgetState extends State<GenreDDWidget> {
  Genre dropdownValue;

  _GenreDDWidgetState(this.dropdownValue);

  @override
  Widget build(BuildContext context) {
    return DropdownButton<Genre>(
      value: dropdownValue,
      icon: Icon(Icons.arrow_drop_down),
      iconSize: 24,
      elevation: 16,
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.deepPurple),
      underline: Container(
        height: 2,
        color: Colors.deepPurpleAccent,
      ),
      isExpanded: true,
      onChanged: (value) {
        setState(() => dropdownValue = value);
        widget.onItemChange(value);
      },
      items: Genre.values
          .map(
            (value) => DropdownMenuItem(
              value: value,
              child: Text(describeEnum(value)),
            ),
          )
          .toList(),
    );
  }
}

//Drop down menu 2 for difficulty level
class LevelDDWidget extends StatefulWidget {
  final Function(DifficultyLevel) onItemChange;
  final DifficultyLevel initial;

  LevelDDWidget({Key key, this.onItemChange, this.initial}) : super(key: key);

  @override
  _LevelDDWidgetState createState() => _LevelDDWidgetState(initial);
}

class _LevelDDWidgetState extends State<LevelDDWidget> {
  DifficultyLevel dropdownValue;

  _LevelDDWidgetState(this.dropdownValue);

  @override
  Widget build(BuildContext context) {
    return DropdownButton<DifficultyLevel>(
      value: dropdownValue,
      icon: Icon(Icons.arrow_drop_down),
      iconSize: 24,
      elevation: 16,
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.pink),
      underline: Container(
        height: 2,
        color: Colors.pinkAccent,
      ),
      isExpanded: true,
      onChanged: (value) {
        setState(() => dropdownValue = value);
        widget.onItemChange(value);
      },
      items: DifficultyLevel.values
          .map(
            (value) => DropdownMenuItem(
              value: value,
              child: Text(describeEnum(value)),
            ),
          )
          .toList(),
    );
  }
}

enum Genre {
  RPG,
  Shooting,
  Sport,
  Racing,
  Random,
}

enum DifficultyLevel {
  Hard,
  Intermediate,
  Easy,
  Random,
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM