Удалить конкретный виджет | Flutter

#flutter #riverpod

#flutter #riverpod

Вопрос:

Как показано на рисунке, я пытаюсь создать список кубиков, в которые я могу добавить или удалить кубик. Я пробовал stateProvider, ChangeNotifier и StateNotifier. Кажется, что каждый из них работает не так, как я ожидаю. Я пытаюсь создать провайдера, который содержит список dieWidgets, но я не могу понять, как удалить конкретный штамп, когда я долго нажимаю на него. На изображении показано всплывающее меню для его удаления, это долгосрочная цель, но сейчас было бы неплохо просто удалить его длинным нажатием. Мысли о том, как подойти к этому?

Виджеты штампов

Код

main.dart

 class DiceNotifier extends ChangeNotifier {
  List<DieWidget> dice = [];

  void add() {
    dice.add(DieWidget());
    notifyListeners();
  }

  void removeDie(int id) {
    // FIXME: Unable to delete a die based on id
    print(id);
    notifyListeners();
  }
}

final diceProvider = ChangeNotifierProvider((_) {
  return DiceNotifier();
});

class MyHomePage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final dice = watch(diceProvider).dice;
    return Scaffold(
      appBar: AppBar(
        title: Text("Dice"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ...dice,
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.read(diceProvider).add();
        },
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
 

die_widget.dart

 class DieWidget extends StatefulWidget {
  @override
  _DieWidgetState createState() => _DieWidgetState();
}

class _DieWidgetState extends State<DieWidget> {
  int value = 0;
  int id = 0;
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text(
        '$value',
      ),
      onPressed: () {
        setState(() {
          value  ;
          id  ;
        });
        // context.read(dieProvider).increment();
      },
      onLongPress: () {
        final dice = context.read(diceProvider);
        dice.removeDie(id);
        // print(this.value);
      },
    );
  }
}
 

Ответ №1:

Одним из решений было бы определить параметр value в DiceWidget классе:

 class DiceWidget extends StatefulWidget {
  const DiceWidget({ Key key, this.value }) : super(key: key);
  int value;
  @override
  _DiceWidgetState createState() => _DiceWidgetState();

}
 

И получить доступ к этим данным из DiceWidget :

 class DiceWidget extends StatefulWidget {
  @override
  _DiceWidgetState createState() => _DiceWidgetState();
}

class _DiceWidgetState extends State<DiceWidget> {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text(
        widget.value.toString() ?? '',
      ),
      onLongPress: () {
        final dice = context.read(diceProvider);
        dice.removeDice(widget.value);
        // print(widget.value);
      },
    );
  }
}
 

В DiceNotifier классе я бы рекомендовал реализовать dices массив как List<int> :

 List<int> dices = [];
 

Следовательно, функции addDice() и removeDice() будут, соответственно:

 class DiceNotifier extends ChangeNotifier {
  List<int> dices = [];

  void addDice() {
    dices.add(dices.length);
    notifyListeners();
  }

  void removeDice(int id) {
    dices.remove(id);
    print(id);
    notifyListeners();
  }
}
 

Чтобы заставить пример работать, нам MyHomePage Column children также нужно изменить, чтобы построить список DiceWidget :

 ...dices.map((d) => DiceWidget(value: d)).toList(),
 

Тогда весь пример будет выглядеть следующим образом:
main.dart :

 class DiceNotifier extends ChangeNotifier {
  List<int> dices = [];

  void addDice() {
    dices.add(dices.length);
    notifyListeners();
  }

  void removeDice(int id) {
    dices.remove(id);
    print(id);
    notifyListeners();
  }
}

final diceProvider = ChangeNotifierProvider((_) {
  return DiceNotifier();
});

class MyHomePage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final dices = watch(diceProvider).dices;
    return Scaffold(
      appBar: AppBar(
        title: Text("Dice"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ...dices.map((d) => DiceWidget(value: d)).toList(),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.read(diceProvider).addDice();
        },
        child: Icon(Icons.add),
      ), 
    );
  }
}
 

dice_widget.dart :

 class DiceWidget extends StatefulWidget {
  @override
  _DiceWidgetState createState() => _DiceWidgetState();
}

class _DiceWidgetState extends State<DiceWidget> {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text(
        widget.value.toString() ?? '',
      ),
      onLongPress: () {
        final dice = context.read(diceProvider);
        dice.removeDice(widget.value);
        print(widget.value);
      },
    );
  }
}
 

Комментарии:

1. Это потрясающе! Большое вам спасибо за ваше время и помощь. Мне нужно еще немного посидеть и разобраться в логике всего этого. Еще раз спасибо 🙂