首页 > 解决方案 > 如何在上下文中结合 Flutter 中的 DropdownMenu 和 AppLocalization?

问题描述

我在与 AppLocalization 一起使用下拉菜单时遇到问题。我已经根据用户在电话设置中选择的语言实现了自动本地化。在我想用本地化值实现下拉菜单之前,它工作得很好。当我渲染下拉菜单时,它可以工作,但是在我选择值后,会出现类似Flutter 的错误:应该只有一个项目具有 [DropdownButton] 的值,请注意我需要在 KeyValueRecords 列表中使用 appLocalization,

import 'package:MyHorse.sk/app_localizations.dart';

class AddNewTrainingFormState extends State<AddNewTrainingForm> {

  KeyValueRecordType recordType;

  @override
  Widget build(BuildContext context) {
    List<KeyValueRecordType> recordTypes = <KeyValueRecordType>[
      KeyValueRecordType(
          key: "dressage",
          value: AppLocalizations.of(context).translate('dressage')),
      KeyValueRecordType(
          key: "cavaletti",
          value: AppLocalizations.of(context).translate('cavaletti')),
      KeyValueRecordType(
          key: "jumping",
          value: AppLocalizations.of(context).translate('jumping')),
      KeyValueRecordType(
          key: "hacking",
          value: AppLocalizations.of(context).translate('hacking')),
      KeyValueRecordType(
          key: "groundwork",
          value: AppLocalizations.of(context).translate('groundwork')),
      KeyValueRecordType(
          key: "competition",
          value: AppLocalizations.of(context).translate('competition')),
      KeyValueRecordType(
          key: "other", value: AppLocalizations.of(context).translate('other')),
    ];

        return Scaffold(
              body: Container(
              child: Theme(
                data: Theme.of(context).copyWith(
                  canvasColor: Colors.black,
                ),
                child: DropdownButton<KeyValueRecordType>(
                  value: recordType,
                  onChanged: (KeyValueRecordType value) {
                    setState(() {
                      recordType = value; //show selected value
                    });
                  },
                  items: recordTypes
                      .map<DropdownMenuItem<KeyValueRecordType>>(
                          (recordType) =>
                              new DropdownMenuItem<KeyValueRecordType>(
                                child: Text(recordType.value),
                                value: recordType,
                              ))
                      .toList(),
                ),
              ),

class KeyValueRecordType {
  String key;
  String value;

  KeyValueRecordType({this.key, this.value});
}

所以错误是:

There should be exactly one item with [DropdownButton]'s value: Instance of 'KeyValueRecordType'.
I/flutter ( 9900): Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
I/flutter ( 9900): 'package:flutter/src/material/dropdown.dart':
I/flutter ( 9900): Failed assertion: line 834 pos 15: 'items == null || items.isEmpty || value == null ||
I/flutter ( 9900):               items.where((DropdownMenuItem<T> item) {
I/flutter ( 9900):                 return item.value == value;
I/flutter ( 9900):               }).length == 1'

我尝试了不同的方法,当我在 onchanged 中指定 recordType.key 时,我收到此键不存在的错误。我也尝试将 List 放在 FutureBuilder 和单独的函数中,但都不起作用。由于我需要 Context 我不能把它放在构建方法之外。

标签: flutterdartdrop-down-menulocalizationkey-value

解决方案


您可以在下面复制粘贴运行完整代码
您可以使用包https://pub.dev/packages/equatable并扩展Equatable
代码片段

import 'package:equatable/equatable.dart';
...
class KeyValueRecordType extends Equatable {
  String key;
  String value;

  KeyValueRecordType({this.key, this.value});

  @override
  List<Object> get props => [key, value];
}

工作演示

在此处输入图像描述

完整代码

import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';

class KeyValueRecordType extends Equatable {
  String key;
  String value;

  KeyValueRecordType({this.key, this.value});

  @override
  List<Object> get props => [key, value];
}

class AddNewTrainingForm extends StatefulWidget {
  @override
  AddNewTrainingFormState createState() => AddNewTrainingFormState();
}

class AddNewTrainingFormState extends State<AddNewTrainingForm> {
  KeyValueRecordType recordType;

  @override
  Widget build(BuildContext context) {
    List<KeyValueRecordType> recordTypes = <KeyValueRecordType>[
      KeyValueRecordType(key: "dressage", value: 'dressage'),
      KeyValueRecordType(key: "cavaletti", value: 'cavaletti'),
      KeyValueRecordType(key: "jumping", value: 'jumping'),
      KeyValueRecordType(key: "hacking", value: 'hacking'),
      KeyValueRecordType(key: "groundwork", value: 'groundwork'),
      KeyValueRecordType(key: "competition", value: 'competition'),
      KeyValueRecordType(key: "other", value: 'other'),
    ];

    return SafeArea(
      child: Scaffold(
          body: Container(
        child: Theme(
          data: Theme.of(context).copyWith(
            canvasColor: Colors.white,
          ),
          child: DropdownButton<KeyValueRecordType>(
            value: recordType,
            onChanged: (KeyValueRecordType value) {
              setState(() {
                recordType = value; //show selected value
              });
            },
            items: recordTypes
                .map<DropdownMenuItem<KeyValueRecordType>>(
                    (recordType) => new DropdownMenuItem<KeyValueRecordType>(
                          child: Text(recordType.value),
                          value: recordType,
                        ))
                .toList(),
          ),
        ),
      )),
    );
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: AddNewTrainingForm(),
    );
  }
}

推荐阅读