#flutter #dart
#флаттер #dart
Вопрос:
Конечно, это простое решение для этого, но я не могу понять это — я совсем новичок в flutter — still. В чем проблема?
У меня есть диалоговое окно с 4 листами списка, которые должны работать как селекторы для радиуса gps, однако у меня проблема с одним выбором. Теперь, когда выбран один — все выбираются одновременно. Итак, мне нужно найти способ, как сделать одиночный выбор для каждого из них (если один выбран, остальные должны быть невыбраны), а затем передать его значение, например. 10, 25 и т.д. при нажатии кнопки «Выбрать».
class RadiusSelectorDialog extends StatefulWidget {
RadiusSelectorDialog({Key key}) : super(key: key);
@override
_RadiusSelectorDialogState createState() => _RadiusSelectorDialogState();
}
class _RadiusSelectorDialogState extends State<RadiusSelectorDialog>
with TitleDescriptionTextMixin {
bool selected = false;
@override
Widget build(BuildContext context) {
return AlertDialog(
scrollable: true,
contentPadding: EdgeInsets.all(4.0),
title: Center(child: smallerBoldText('Select radius:', fontSize: 15.0)),
content: Column(
children: [
Divider(
color: Colors.grey,
height: 2.0,
),
CustomListTile(
label: '10 km',
selected: selected,
onSelect: () => _onSelect(selected),
),
CustomListTile(
label: '25 km',
selected: selected,
onSelect: () => _onSelect(selected),
),
CustomListTile(
label: '50 km',
selected: selected,
onSelect: () => _onSelect(selected),
),
CustomListTile(
label: '75 km',
selected: selected,
onSelect: () => _onSelect(selected),
),
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16.0))),
actions: [
FlatButton(
child: Text('Select',
style: TextStyle(
color: LegionColors.primaryRedHigh,
fontWeight: FontWeight.bold)),
onPressed: () {
Navigator.pop(context);
})
],
);
}
void _onSelect(bool value) {
setState(() {
if (selected == false) {
selected = true;
} else {
selected = false;
}
});
}
}
Мой пользовательский список для выбора.
class CustomListTile extends StatelessWidget {
final String label;
final bool selected;
final Function onSelect;
const CustomListTile(
{Key key,
@required this.selected,
@required this.onSelect,
@required this.label})
: super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
ListTile(
title: Center(
child: Text(label,
style: selected == false
? TextStyle(color: Colors.black)
: TextStyle(
color: LegionColors.primaryRedHigh,
fontWeight: FontWeight.bold,
))),
selected: selected,
onTap: onSelect,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16.0))),
),
Divider(
color: Colors.grey,
height: 2.0,
),
],
);
}
}
Ответ №1:
Вы используете одну и ту же переменную selected
, чтобы определить, выбран ли элемент для всех элементов. Вот что происходит,
- Задействован один элемент
- setState -> selected -> true
- Все элементы обновляются, чтобы быть
selected
Чтобы избежать этого
- вы можете переместить идентификатор внутри
CustomListTile
и сделать его StatefulWidget. - Или, если вам нужно поддерживать статус выбора в родительском элементе, вы можете использовать
Map
реализацию
HashMap<String, bool> selectedState = new HashMap();
void updateSelectionStatus(String selectedTileId, bool status) {
setState(() {
selectedState[selectedTileId] = status;
});
}
И тогда вы можете использовать его следующим образом
CustomListTile(
label: '75 km',
selected: selectedState['your-unique-id'],
onSelect: () => updateSelectionStatus('your-unique-id', !selectedState['your-unique-id']),
)
Комментарии:
1. Devayan Sarkar — кажется, это хорошее решение (с map), однако теперь оно показывает, что выбранное значение равно нулю — я даже меняю свойство customtile на значение «flase» по умолчанию, но selectedState каким-то образом очищает его и передает ему значение null.
2. Вы заполнили
selectedState
?dart @override void initState() { super.initState(); setState(() { selectedState['tile1'] = false; selectedState['tile2'] = false; selectedState['tile3'] = false; selectedState['tile4'] = false; }); }
3. Теперь это почти префект 🙂 Мне нужно заблокировать другие плитки для выбора. Чтобы сделать его единым списком выбора. Я думаю о инструкции switch.
4. Если вы пытаетесь выбрать только один из них. Тогда я бы предложил альтернативный подход.
dart int selectedItem = 0 ; void updateSelectedItem(int index){ setState(() { _selectedIndex = index; }); } // Use it like this CustomListTile( label: '75 km', selected: 1 == selectedItem, onSelect: () => updateSelectedItem(1), ) CustomListTile( label: '85 km', selected: 2 == selectedItem, onSelect: () => updateSelectedItem(2), )
Ответ №2:
Проверьте его рабочий код на официальном веб-сайте Flutter https://api.flutter.dev/flutter/material/ListTile/selected.html