Flutter как показать AlertDialog только на определенной странице

#flutter #dart #flutter-animation

#flutter #dart #flutter-анимация

Вопрос:

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

Я использую провайдера для управления состоянием, когда я меняю продолжительность, я меняю значение bool на true. затем на домашней странице я проверяю, имеет ли значение bool значение true, а затем запускаю код диалогового окна оповещения. Я попытался ввести код диалогового future delay.Zero окна, но это не сработало.

прямо сейчас домашняя страница перестраивается сразу после изменения настроек, и появляется диалоговое окно оповещения.

мой код:

 // home page code
class HomePage extends StatefulWidget {
  const HomePage({
    Key? key,
  }) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}


class _HomePageState extends State<HomePage>
    with TickerProviderStateMixin, WidgetsBindingObserver {

// code for initstate and logic

late AnimationController _whiteControl;
  late AnimationController _blackControl;

  int whiteTime = 1;
  int blackTime = 1;

 @override
  void initState() {
    super.initState();

    WidgetsBinding.instance!.addObserver(this);

    _whiteControl = AnimationController(
      vsync: this,
      duration: Duration(seconds: whiteTime * 60),
    );

    _blackControl = AnimationController(
      vsync: this,
      duration: Duration(seconds: blackTime * 60),
    );

@override
  void dispose() {
    WidgetsBinding.instance!.removeObserver(this);
    _whiteControl.dispose();
    _blackControl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var gameState = Provider.of<GameState>(context, listen: false);
    final ChoiceDialog resetChoice = ChoiceDialog(
      buttonOkOnPressed: () {
        _blackControl.reset();
        _whiteControl.reset();
        gameState.isgameChanged = false;
        Navigator.pop(context);
      },
      buttonCancelOnPressed: () {
        gameState.isgameChanged = false;
        Navigator.pop(context);
      },
    );

    if (gameState.isGameStarted amp;amp; gameState.isgameChanged) {
      Future.delayed(Duration.zero, () {
        print('👉 Game Changed ');
        resetChoice.show(context);
      });
    }
 print('🏠 Rebuilding Home Page ---');
    return Scaffold();
//reset of homepage code

 

Код страницы настроек:

 
class SettingsPage extends StatelessWidget {
  const SettingsPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Settings'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
                itemCount: gamesList.length,
                itemBuilder: (context, index) {
                  return Consumer<GameState>(
                    builder: (context, _gameState, child) {
                      return GestureDetector(
                        onTap: () {
                          _gameState.changeGame(gamesList[index]);
                        },
                        child: Container(),
                      );
                    },
                  );
                }),
          )
        ],
      ),
    );
  }
}
 

Логика состояния поставщика:

 
class Game {
  final String name;
  final int whiteTime;
  final int blackTime;

  Game({
    required this.name,
    required this.whiteTime,
    required this.blackTime,
  });
}

class GameState with ChangeNotifier {
  bool turnWhite = false;
  bool turnBlack = false;
  bool isgameChanged = false;
  bool isClocksFinished = false;
  bool isPaused = false;
  bool isGameStarted = false;
  bool resetGame = false;

  int white = 0;
  int black = 0;

  Game _currentGame = gamesList[0];

  Game get currentGame => _currentGame;

  bool get isWhiteTurn => turnWhite;

  void resetGameClocks() {
    resetGame = true;
    notifyListeners();
  }

  void setTurnWhite() {
    turnWhite = true;
    turnBlack = false;
    isGameStarted = true;
    notifyListeners();
  }

  void setTurnBlack() {
    turnWhite = false;
    turnBlack = true;
    isGameStarted = true;
    notifyListeners();
  }

  void changeGame(Game game) {
    _currentGame = game;
    isgameChanged = true;
    white = game.whiteTime;
    black = game.blackTime;
    notifyListeners();
  }
}
 

репозиторий проекта: https://github.dev/tonydavidx/chess-clock-app/tree/dev

Ответ №1:

Я проверил ваш код, вы допустили ошибку в самой начальной точке / начальной точке экрана домашней страницы, пожалуйста, избегайте этого

никогда не инициализируйте и не помещайте свой код перед возвратом в функцию сборки виджетов, если вам действительно нужна какая-то логика или код, который нужно выполнить в начале, затем поместите его внутрь initstate() или внутри вашего конструктора провайдера и обработайте его должным образом.

это основная причина проблемы, с которой вы столкнулись.

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

1. Я инициализировал контроллеры анимации в initstate том, что когда я хочу сбросить длительность, я проверяю, выполняется ли определенное условие при каждой сборке страницы, и запускаю диалоговое окно предупреждения о сбросе кода. пожалуйста, проверьте мой репозиторий проекта: github.dev/tonydavidx/chess-clock-app /tree/dev

2. поместите логику кода сброса внутрь a initstate и правильно управляйте состоянием, вся проблема в вашей технике управления состоянием или в более коротком состоянии протекает 😉