Flutterにドロップダウンリストとして実装したい場所のリストがあります。私は言語にかなり新しいです。これが私がやったことです。
new DropdownButton(
value: _selectedLocation,
onChanged: (String newValue) {
setState(() {
_selectedLocation = newValue;
});
},
items: _locations.map((String location) {
return new DropdownMenuItem<String>(
child: new Text(location),
);
}).toList(),
これは私のアイテムのリストです:
List<String> _locations = ['A', 'B', 'C', 'D'];
そして、次のエラーが表示されます。
Another exception was thrown: 'package:flutter/src/material/dropdown.Dart': Failed assertion: line 468 pos 15: 'value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1': is not true.
_selectedLocation
の値がnullになっていると思います。しかし、私はそれをそのように初期化しています。
String _selectedLocation = 'Please choose a location';
これを試して
new DropdownButton<String>(
items: <String>['A', 'B', 'C', 'D'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (_) {},
)
まず、エラーの内容を調べてみましょう(Flutter 1.2でスローされるエラーを引用しましたが、考え方は同じです)。
失敗したアサーション:560行目15: 'items == null || items.isEmpty ||値== null || items.where((DropdownMenuItem item)=> item.value == value).length == 1 ':正しくありません。
4つのor
条件があります。それらの少なくとも1つを満たす必要があります。
DropdownMenuItem
ウィジェットのリスト)が提供されました。これにより、items == null
がなくなります。items.isEmpty
がなくなります。_selectedLocation
)も与えられました。これにより、value == null
がなくなります。これはDropdownButton
の値であり、DropdownMenuItem
の値ではないことに注意してください。したがって、最後のチェックのみが残ります。要約すると次のようになります。
DropdownMenuItem
を繰り返し処理します。_selectedLocation
と等しいvalue
を持つすべてを検索します。次に、一致するアイテムがいくつ見つかったかを確認します。この値を持つウィジェットは1つだけ存在する必要があります。それ以外の場合は、エラーをスローします。
コードの表示方法には、_selectedLocation
の値を持つDropdownMenuItem
ウィジェットはありません。代わりに、すべてのウィジェットの値はnull
に設定されています。 null != _selectedLocation
なので、最後の条件は失敗します。 _selectedLocation
をnull
に設定してこれを確認します-アプリが実行されます。
この問題を修正するには、最初に各DropdownMenuItem
に値を設定する必要があります(何かがonChanged
コールバックに渡されるように):
return DropdownMenuItem(
child: new Text(location),
value: location,
);
アプリは引き続き失敗します。これは、リストに_selectedLocation
の値がまだ含まれていないためです。次の2つの方法でアプリを機能させることができます。
items.where((DropdownMenuItem<T> item) => item.value == value).length == 1
を満たすために)値を持つ別のウィジェットを追加します。ユーザーがPlease choose a location
オプションを再選択できるようにする場合に便利です。hint:
パラメーターに何かを渡し、selectedLocation
をnull
に設定します(value == null
条件を満たすため)。 Please choose a location
をオプションのままにしたくない場合に便利です。その方法を示す以下のコードを参照してください。
import 'package:flutter/material.Dart';
void main() {
runApp(Example());
}
class Example extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
// List<String> _locations = ['Please choose a location', 'A', 'B', 'C', 'D']; // Option 1
// String _selectedLocation = 'Please choose a location'; // Option 1
List<String> _locations = ['A', 'B', 'C', 'D']; // Option 2
String _selectedLocation; // Option 2
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: DropdownButton(
hint: Text('Please choose a location'), // Not necessary for Option 1
value: _selectedLocation,
onChanged: (newValue) {
setState(() {
_selectedLocation = newValue;
});
},
items: _locations.map((location) {
return DropdownMenuItem(
child: new Text(location),
value: location,
);
}).toList(),
),
),
),
);
}
}
これを考慮する必要があります(DropdownButtonドキュメントから):
「アイテムには個別の値が必要です。値がnullでない場合は、アイテムに含まれている必要があります。」
基本的に、この文字列のリストがあります
List<String> _locations = ['A', 'B', 'C', 'D'];
そして、ドロップダウン値プロパティの値は次のように初期化されます。
String _selectedLocation = 'Please choose a location';
このリストを試してください:
List<String> _locations = ['Please choose a location', 'A', 'B', 'C', 'D'];
それは動作するはずです:)
また、(リストコンテキストから)そのような文字列を追加したくない場合は、「ヒント」プロパティを確認してください。次のようなものを使用できます。
DropdownButton<int>(
items: locations.map((String val) {
return new DropdownMenuItem<String>(
value: val,
child: new Text(val),
);
}).toList(),
hint: Text("Please choose a location"),
onChanged: (newVal) {
_selectedLocation = newVal;
this.setState(() {});
});
動作させるには、コードにvalue: location
を追加する必要があります。 this outを確認してください。
items: _locations.map((String location) {
return new DropdownMenuItem<String>(
child: new Text(location),
value: location,
);
}).toList(),
アイテム内に値を配置します。それが機能します。
new DropdownButton<String>(
items:_dropitems.map((String val){
return DropdownMenuItem<String>(
value: val,
child: new Text(val),
);
}).toList(),
hint:Text(_SelectdType),
onChanged:(String val){
_SelectdType= val;
setState(() {});
})
ドロップダウンリストを作成するためにDropDownButton
クラスを使用できます:
...
...
String dropdownValue = 'One';
...
...
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: DropdownButton<String>(
value: dropdownValue,
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
);
...
...
これを参照してください flutter web page
デフォルト値を新しい動的な値に置き換えたときに、それが私に起こりました。しかし、どういうわけかあなたのコードはそのデフォルト値に依存しているかもしれません。したがって、フォールバックするためにどこかに保存されているデフォルト値で定数を維持してみてください。
const defVal = 'abcd';
String dynVal = defVal;
// dropdown list whose value is dynVal that keeps changing with onchanged
// when rebuilding or setState((){})
dynVal = defVal;
// rebuilding here...
通貨のドロップダウンリストを作成しているとしましょう:
List _currency = ["INR", "USD", "SGD", "EUR", "PND"];
List<DropdownMenuItem<String>> _dropDownMenuCurrencyItems;
String _currentCurrency;
List<DropdownMenuItem<String>> getDropDownMenuCurrencyItems() {
List<DropdownMenuItem<String>> items = new List();
for (String currency in _currency) {
items.add(
new DropdownMenuItem(value: currency, child: new Text(currency)));
}
return items;
}
void changedDropDownItem(String selectedCurrency) {
setState(() {
_currentCurrency = selectedCurrency;
});
}
本文部分に以下のコードを追加:
new Row(children: <Widget>[
new Text("Currency: "),
new Container(
padding: new EdgeInsets.all(16.0),
),
new DropdownButton(
value: _currentCurrency,
items: _dropDownMenuCurrencyItems,
onChanged: changedDropDownItem,
)
])
あまり一般的ではないDropdownStringButtonが欲しいというこの問題に遭遇したとき、私はそれを作成しました:
dropdown_string_button.Dart
import 'package:flutter/material.Dart';
// Subclass of DropdownButton based on String only values.
// Yes, I know Flutter discourages subclassing, but this seems to be
// a reasonable exception where a commonly used specialization can be
// made more easily usable.
//
// Usage:
// DropdownStringButton(items: ['A', 'B', 'C'], value: 'A', onChanged: (string) {})
//
class DropdownStringButton extends DropdownButton<String> {
DropdownStringButton({
Key key, @required List<String> items, value, hint, disabledHint,
@required onChanged, elevation = 8, style, iconSize = 24.0, isDense = false,
isExpanded = false, }) :
assert(items == null || value == null || items.where((String item) => item == value).length == 1),
super(
key: key,
items: items.map((String item) {
return DropdownMenuItem<String>(child: Text(item), value: item);
}).toList(),
value: value, hint: hint, disabledHint: disabledHint, onChanged: onChanged,
elevation: elevation, style: style, iconSize: iconSize, isDense: isDense,
isExpanded: isExpanded,
);
}
変化する
List<String> _locations = ['A', 'B', 'C', 'D'];
に
List<String> _locations = [_selectedLocation, 'A', 'B', 'C', 'D'];
_selectedLocationは、アイテムリストの一部である必要があります。
取得しているエラーは、nullオブジェクトのプロパティを要求することが原因です。あなたのアイテムはnullでなければならないので、その値を比較するように頼むとき、あなたはそのエラーを得ています。データを取得していること、またはリストがオブジェクトのリストであり、単純な文字列ではないことを確認してください。
ドロップダウンで文字列の動的リストを表示しようとしたときに、DropDownButtonで同様の問題に直面していました。プラグインを作成することになった: flutter_search_panel 。ドロップダウンプラグインではありませんが、検索機能を使用してアイテムを表示できます。
ウィジェットを使用するには、次のコードを使用します。
FlutterSearchPanel(
padding: EdgeInsets.all(10.0),
selected: 'a',
title: 'Demo Search Page',
data: ['This', 'is', 'a', 'test', 'array'],
icon: new Icon(Icons.label, color: Colors.black),
color: Colors.white,
textStyle: new TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20.0, decorationStyle: TextDecorationStyle.dotted),
onChanged: (value) {
print(value);
},
),