Flutter - вызывает функцию анимации дочернего элемента из родительского или другого дочернего класса. - PullRequest
3 голосов
/ 07 марта 2019

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

class dropDownMenu extends StatefulWidget {
  final Function() onPressed;
  final String tooltip;
  final IconData icon;
  final _callback;

  dropDownMenu({Key key, this.onPressed, this.tooltip, this.icon, @required void singlePlayerCallbacks(String callBackType) }  ):
      _callback = singlePlayerCallbacks, super(key: key);

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

 class _dropDownMenuState extends State<dropDownMenu>
   with SingleTickerProviderStateMixin {

   @override
   Widget build(BuildContext context) {
     return Stack(
       children: <Widget> [
         Column(
          Container(
          child: Opacity(
            opacity: 0.0,
            child: FloatingActionButton(
              heroTag: null,
              onPressed:  isOpened == true? (){
                widget?._callback('dice');
              } : () {},
            ),
          ),
        ),
      ],
    );
  }

А потом в родительском классе:

class SinglePlayerMode extends StatefulWidget {
  @override
  SinglePlayerModeParentState createState() => SinglePlayerModeParentState();
}

class SinglePlayerModeParentState extends State<SinglePlayerMode> {

callBacks(String callBackType) {
  switch(callBackType) {
    case 'dice':
    {
        diceVisible = !diceVisible;
        int rng = new Random().nextInt(19) + 1;
        setState(() {
          diceResult = rng;
        });
      }
    }
  break;
}

@override
Widget build(BuildContext context) {
  child: Scaffold(
    body: Container(
      Padding(
          padding: EdgeInsets.all(0.0),
          child: dropDownMenu(
            singlePlayerCallbacks: callBacks,
          ),
        ),
      ),
    ),
  }

В качестве быстрого примера, и это прекрасно работает.

Что мне нужно сделать дальше, так это создать другое анимированное меню, которое называется styleMenu, которое анимируется при нажатии кнопки из dropDownMenu. Здесь я сталкиваюсь с огромными препятствиями. Честно говоря, я не против, КАК я это сделаю, мне просто нужно это сделать. Это то, что я сейчас пытаюсь, но безуспешно:

В dropDownMenu у меня есть еще одна кнопка с обратным вызовом для родителя:

Container(
  child: Opacity(
    opacity: 0.0,
    child: FloatingActionButton(
      heroTag: null,
      onPressed:  isOpened == true? (){
        widget?._callback('theme');
      } : () {},
    ),
  ),
),

, который снова вызывает функцию обратного вызова родителя, с другим регистром переключения:

callBacks(String callBackType) {
  case 'theme':
    {
      styleMenuState().animate();
    }
  break;

Я, очевидно, не могу этого сделать, потому что он говорит мне, что я пытаюсь оживить нулевой объект. Как будто я каким-то образом должен создать экземпляр styleMenu, прежде чем я смогу вызвать эту функцию отсюда, но я не знаю, как это сделать, или даже если это возможно.

Мой класс styleMenu (выдержка):

class styleMenu extends StatefulWidget {
 final Function() onPressed;
 final String tooltip;
 final IconData icon;
 final _callback;
 final VoidCallback animate;

 styleMenu({this.onPressed, this.tooltip, this.animate, this.icon, @required void singlePlayerCallbacks(String callBackType) }  ):
       _callback = singlePlayerCallbacks;

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


class styleMenuState extends State<styleMenu>
    with SingleTickerProviderStateMixin {
  bool isOpened = false;
  AnimationController animationController;
  Animation<Color> _buttonColor;
  Animation<double> _animateIcon;
  Animation<double> _translateButton;
  Curve _curve = Curves.easeOut;
  double _fabHeight = 52.0;

  @override
  initState() {
    animationController =
    AnimationController(vsync: this, duration: Duration(milliseconds: 600))
      ..addListener(() {
        setState(() {});
      });
    _animateIcon =
        Tween<double>(begin: 0.0, end: 1.0).animate(animationController);
    _buttonColor = ColorTween(
      begin: Colors.blue,
      end: Colors.red,
    ).animate(CurvedAnimation(
      parent: animationController,
      curve: Interval(
        0.0,
        1.0,
        curve: Curves.linear,
      ),
    ));
    _translateButton = Tween<double>(
      begin: 0.0,
      end: _fabHeight,
    ).animate(CurvedAnimation(
      parent: animationController,
      curve: Interval(
        0.0,
        1.0,
        curve: _curve,
      ),
    ));
    super.initState();
  }

  @override
  dispose() {
    animationController.dispose();
    super.dispose();
  }

  animate() {
    if (!isOpened) {
      styleMenuState().animationController.forward();
    } else {
      styleMenuState().animationController.reverse();
    }
    isOpened = !isOpened;
  }

@override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget> [
        Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Stack(
              children: <Widget>[
                Transform(
                  transform: Matrix4.translationValues(
                    0,
                    _translateButton.value,
                    0,
                  ),
                  child: blueTheme(),
                ),
               Transform(
                  transform: Matrix4.translationValues(
                    0,
                   _translateButton.value * 2,
                    0,
                  ),
                  child: greenTheme(),
                ),
                Transform(
                  transform: Matrix4.translationValues(
                    0,
                    _translateButton.value * 3,
                    0,
                  ),
                  child: redTheme(),
                ),
            blackTheme(),
          ],
        ),
      ],
    ),
  );
 } 

Опять же, мне просто нужно иметь возможность запускать функцию анимации из styleMenu для вызова этого меню, нажимая кнопку внутри dropDownMenu, и я просто не могу понять, как это сделать! Я уверен, что должен быть простой способ, но я ничего не могу найти в Интернете.

Есть ли плюсы?

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