Flutter update Reorderable ListView, когда флажок в AlertDialog установлен или не установлен - PullRequest
0 голосов
/ 01 мая 2020

В настоящее время я работаю над мобильным приложением Flutter, которое должно работать на Android и IOS. У меня проблема с ListView и его обновлением.

Я знаю, что со многими вещами я поступаю неправильно, но я учусь и хотел бы научиться правильно. Поэтому, если у вас есть какие-либо комментарии, советы по поводу кода, который им дается :)

По сути, вот что он делает: Основной игрок сам выберет, кто будет играть с ним в игре через AlertDialog, внутри которого есть CheckboxList. и каждый раз, когда он выбирает игрока, он обновляет список с именем choosenPlayers, в котором есть все выбранные объекты игрока.

Затем я хочу отобразить список всех выбранных игроков (переупорядочиваемый список изменить порядок игроков) и обновлять его каждый раз, когда обновляется список choosenPlayers.

Мне удалось отобразить этих игроков, но я должен перезагрузить страницу, зайдя в меню ящика и щелкнув ссылку на страницу, чтобы увидеть добавленные игроки.

Я использую виджет с отслеживанием состояния для своего переупорядочиваемого списка игроков и передаю родителю список игроков (это не самый лучший способ сделать это, я знаю):

import 'package:flutter/material.dart';
import 'package:mollky/models/player.dart';

class ChoosenPlayers extends StatefulWidget {
  _ChoosenPlayersState _choosenPlayersState = _ChoosenPlayersState();
  List<Player> choosenPlayers = [];
  ChoosenPlayers({Key key, this.choosenPlayers}) : super(key: key);

  @override
  _ChoosenPlayersState createState() => _choosenPlayersState;
}

class _ChoosenPlayersState extends State<ChoosenPlayers> {
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return ReorderableListView(
      onReorder: onReorder,
      children: getListItems(),
    );
  }

  List<ListTile> getListItems() => widget.choosenPlayers
      .asMap()
      .map((i, item) => MapEntry(i, buildTenableListTile(item, i)))
      .values
      .toList();

  ListTile buildTenableListTile(Player item, int index) {
    return ListTile(
      key: ValueKey(item.id),
      title: Text(item.nickname + " " + item.name),
      leading: Text("#${index + 1}"),
    );
  }

  void onReorder(int oldIndex, int newIndex) {
    if (newIndex > oldIndex) {
      newIndex -= 1;
    }

    setState(() {
      Player reOrderedPlayer = widget.choosenPlayers[oldIndex];

      widget.choosenPlayers.removeAt(oldIndex);
      widget.choosenPlayers.insert(newIndex, reOrderedPlayer);
    });
  }
}

Здесь это код главной страницы, где отображается переупорядочиваемый список и отображается AlertDialog. Извините, я не смог отформатировать с помощью Dart, не запускайте код, очевидно Я хочу.

Это настоящий кошмар xD. Извините за французские слова, кстати, я могу перевести, если нужно, но они не важны, простой текст.

Вот два скриншота списка и диалоговое окно предупреждения:

enter image description here

enter image description here

Заранее спасибо:)

1 Ответ

0 голосов
/ 01 мая 2020

Состояние родительского виджета не обновляется. Поэтому, хотя плательщик добавлен в список. Но не показано в родительском виджете. Вызванный setState обновляет только состояние StatefulBuilder , а не NewGame . Проверьте код ниже.

demo

  import 'package:flutter/material.dart';

void main() => runApp(MyApp());

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

class NewGameScreen extends StatefulWidget {
  @override
  _NewGameScreenState createState() => _NewGameScreenState();
}

class _NewGameScreenState extends State<NewGameScreen> {
  List<Player> _availablePlayers = [];
  List<Player> _selectedPlayers = [];

  @override
  void initState() {
    super.initState();
    _availablePlayers = [
      Player(id: 0, name: "Ross", nickname: "Geller", picture: "test"),
      Player(id: 1, name: "Rachel", nickname: "Green", picture: "test"),
      Player(id: 2, name: "Chandler", nickname: "Bing", picture: "test"),
    ];
  }

  _selectPlayer() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("Existing players"),
          content: Stack(
            overflow: Overflow.visible,
            children: <Widget>[
              Positioned(
                right: -40.0,
                top: -40.0,
                child: InkResponse(
                  onTap: () {
                    Navigator.of(context).pop();
                  },
                  child: CircleAvatar(
                    child: Icon(Icons.close),
                    backgroundColor: Colors.lightBlue,
                  ),
                ),
              ),
              StatefulBuilder(
                builder: (BuildContext context, StateSetter alertState) {
                  return Container(
                    width: 350.0,
                    height: 150.0,
                    child: ListView.builder(
                      itemCount: _availablePlayers.length,
                      itemBuilder: (context, playerIndex) {
                        return CheckboxListTile(
                          title:
                              Text(_availablePlayers[playerIndex].nickname + " " + _availablePlayers[playerIndex].name),
                          value: _selectedPlayers.contains(_availablePlayers[playerIndex]),
                          onChanged: (bool value) {
                            if (_selectedPlayers.contains(_availablePlayers[playerIndex])) {
                              _selectedPlayers.remove(_availablePlayers[playerIndex]);
                            } else {
                              _selectedPlayers.add(_availablePlayers[playerIndex]);
                            }
                            setState(() {});//ALSO UPDATE THE PARENT STATE
                            alertState(() {});
                          },
                          secondary: const Icon(Icons.hourglass_empty),
                        );
                      },
                    ),
                  );
                },
              ),
            ],
          ),
        );
      },
    );
  }

  _onReorder(int oldIndex, int newIndex) {
    if (newIndex > oldIndex) {
      newIndex -= 1;
    }
    print('oldIndex:$oldIndex');
    print('newIndex:$newIndex');
    setState(() {
      Player player = _selectedPlayers[newIndex];
      _selectedPlayers[newIndex] = _selectedPlayers[oldIndex];
      _selectedPlayers[oldIndex] = player;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("New Game")),
      body: Column(
        children: <Widget>[
          Card(
            child: ListTile(
              leading: Icon(Icons.people),
              title: Text("Choose players"),
              onTap: _selectPlayer,
            ),
          ),
          Flexible(
            child: ReorderableListView(
              onReorder: _onReorder,
              children: _selectedPlayers.map((player) {
                return ListTile(
                  key: ValueKey(player.id),
                  title: Text(player.nickname + " " + player.name),
                  leading: Text("#${_selectedPlayers.indexOf(player) + 1}"),
                );
              }).toList(),
            ),
          ),
        ],
      ),
    );
  }
}

class Player {
  int id;
  String name;
  String nickname;
  String picture;

  Player({this.id, this.name, this.nickname, this.picture});
}

Надеюсь, это поможет:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...