Как правильно начать и закончить или анимацию и изменение текста из флаттера другого класса

Я изучаю флаттер, и я хочу начать анимацию и установить «синхронизацию» заголовка панели приложения из ответа AlertDialog (в основном из другого класса), затем завершить анимацию и снова установить заголовок после операции Async.

Итак, в настоящее время я добиваюсь этого с помощью GlobalKey и Riverpod (StateNotifier). Создал MainScreen GlobalKey и использовал этот GlobalKey из другого класса перед операцией Async, которую я вызываю

      mainScreenScaffoldKey.currentState.context
      .read(syncProgressProvider)
      .setSyncing();

и завершение анимации после асинхронной операции:

       mainScreenScaffoldKey.currentState.context
      .read(syncProgressProvider)
      .syncProgressDone();

код:

      Map<String, dynamic> dialogResponse = await showDialog(
    context: context,
    builder: (context) => EditNoteScreen(
          _index,
          _task,
          _color,
          dateTime,
          priority: priority,
        ));
if (dialogResponse != null) {
  mainScreenScaffoldKey.currentState.context
      .read(syncProgressProvider)
      .setSyncing();
  await SaveToLocal().save(context.read(listStateProvider.state));
  await CloudNotes().updateCloudNote(
    task: dialogResponse["task"],
    priority: dialogResponse["priority"],
    dateTime: dateTime.toString(),
    index: dialogResponse["index"],
  );
  mainScreenScaffoldKey.currentState.context
      .read(syncProgressProvider)
      .syncProgressDone();
}

и переменная прослушивания в свойстве заголовка AppBar в MainScreen

Я считаю это неправильным подходом или нет?

вот несколько дополнительных фрагментов syncProgressProiver:

       class SyncProgressModel extends StateNotifier<bool>{

 SyncProgressModel() : super(false);

 syncProgressDone(){
   state =false;
 }
 setSyncing(){
   state =true;
 }

Заголовок панели приложений MainScreen

      Consumer(
      builder: (context, watch, child) {
        var syncProgress = watch(syncProgressProvider.state);
        if (!syncProgress) {
          return const Text('To-Do List');
        } else {
          return Row(
            children: [
              const Text('Syncing..'),
              Container(
                margin: const EdgeInsets.only(left: 10),
                width: 25,
                height: 25,
                child: CircularProgressIndicator(
                  strokeWidth: 2,
                  valueColor: animColors,
                ),
              )
            ],
          );
        }
      },
    ),

Так

1 ответ

Я ничего не знаю о ваших анимациях (вы на самом деле не разделяете никакой этой логики или того, что вы имеете в виду initState), но если единственное, что вы хотите, - это анимировать цвет CircularProgressIndicator, тогда вы можете просто создать StatefulWidget который делает это за вас и призывает его строить только тогда, когда syncProgress == true

      class AnimatedWidget extends StatefulWidget {
  AnimatedWidget({Key key}) : super(key: key);

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

class _AnimatedWidgetState extends State<AnimatedWidget>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  final Animatable<Color> _colorTween = TweenSequence<Color>([
    TweenSequenceItem<Color>(
      tween: ColorTween(begin: Colors.red, end: Colors.amber),
      weight: 20,
    ),
    TweenSequenceItem<Color>(
      tween: ColorTween(begin: Colors.amber, end: Colors.green),
      weight: 20,
    ),
    TweenSequenceItem<Color>(
      tween: ColorTween(begin: Colors.green, end: Colors.blue),
      weight: 20,
    ),
    TweenSequenceItem<Color>(
      tween: ColorTween(begin: Colors.blue, end: Colors.purple),
      weight: 20,
    ),
    TweenSequenceItem<Color>(
      tween: ColorTween(begin: Colors.purple, end: Colors.red),
      weight: 20,
    ),
    
  ]).chain(CurveTween(curve: Curves.linear));

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 5),
      animationBehavior: AnimationBehavior.preserve,
      vsync: this,
    )..repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const Text('Syncing..'),
        Container(
          margin: const EdgeInsets.only(left: 10),
          width: 25,
          height: 25,
          child: CircularProgressIndicator(
            strokeWidth: 2,
            valueColor: _colorTween.animate(_controller)
          ),
        )
      ],
    );
  }
}

и в вашем потребителе просто вызовите его, виджет сам обработает анимацию

      Consumer(
      builder: (context, watch, child) {
        var syncProgress = watch(syncProgressProvider.state);
        if (!syncProgress) {
          return const Text('To-Do List');
        } else {
          return AnimatedWidget(); //right here
        }
      },
    ),
Другие вопросы по тегам