Запустить анимацию SlideTransition из метода - PullRequest
0 голосов
/ 13 января 2020

Я пытался заставить Контейнер переместиться из нижней части экрана в середину, когда я нажимал кнопку. Однако я не могу понять, как правильно выполнить анимацию, только когда нажимаю кнопку. Кроме того, кажется, что когда я вызываю метод _customWidget.startAnimation (), всегда возникает ошибка, в которой я назвал функцию void. Вот мои вопросы:

Как правильно получить доступ к startAnimation () внутри MyCustomWidget и как мне структурировать код для запуска анимации только при нажатии кнопки?

Main.dart:

import 'package:flutter/material.dart';
import 'MyCustomWidget.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  MyCustomWidget _customWidget;

  @override
  void initState() {
    super.initState();
    _customWidget = MyCustomWidget();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Center(
          child: MyCustomWidget(),
        ),
        FloatingActionButton(
          onPressed: () => {} //_customWidget.startAnimation() gives an error,
        )
      ],
    );
  }
}

MyCustomWidget.dart:

import 'package:flutter/material.dart';

class MyCustomWidget extends StatefulWidget {
  @override
  _MyCustomWidgetState createState() => _MyCustomWidgetState();

  startAnimation() {
    debugPrint('is this where the function should be?');
  }
}

class _MyCustomWidgetState extends State<MyCustomWidget>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<Offset> _offsetAnimation;

  void startAnimation() {
    debugPrint('or is it here?');
  }

  @override
  void initState() {
    super.initState();
    //Following code should go in startAnimation() rather than letting it execute
    //every time the object is created
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    )..repeat(reverse: true);
    _offsetAnimation = Tween<Offset>(
      begin: Offset.zero,
      end: const Offset(1.5, 0.0),
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.elasticIn,
    ));
  }

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _offsetAnimation,
      child: Container(
        color: Colors.white,
        height: 50,
        width: 50,
      ),
    );
  }

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

Ответы [ 2 ]

1 голос
/ 13 января 2020

В Flutter вы получаете доступ к дочерним виджетам, используя key. Вы также должны сделать состояние publi c (уберите подчеркивание из _MyCustomWidgetState)

Так в дочернем:

class MyCustomWidget extends StatelessWidget {
     final Key key;
     MyCustomWidget(this.key) : super(key: key);
     [...]

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

GlobalKey<MyCustomWidgetState> key = GlobalKey<MyCustomWidgetState>();
[...]
Center(
     child: MyCustomWidget(key)
)

и вызов ребенка (от родителя):

key.currentState.startAnimation();
0 голосов
/ 13 января 2020

Ответ Тиена заставил мой виджет работать правильно, вот как выглядят два файла после изменений:

Main.dart

import 'package:flutter/material.dart';
import 'MyCustomWidget.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey<MyCustomWidgetState> _customWidgetKey =
      GlobalKey<MyCustomWidgetState>();

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Center(
          child: MyCustomWidget(_customWidgetKey),
        ),
        FloatingActionButton(
          onPressed: () => _customWidgetKey.currentState.show(),
        )
      ],
    );
  }
}

MyCustomWidget.dart:

import 'package:flutter/material.dart';

class MyCustomWidget extends StatefulWidget {
  final Key key;
  MyCustomWidget(this.key) : super(key: key);

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

class MyCustomWidgetState extends State<MyCustomWidget>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<Offset> _offsetAnimation;

  void show() {
    setState(() {
      _animationController.animateTo(1.0);
    });
  }

  void hide() {
    setState(() {
      _animationController.animateTo(0.0);
    });
  }

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    );
    _offsetAnimation = Tween<Offset>(
      begin: Offset(0.0, 40),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOutQuint,
    ));
  }

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _offsetAnimation,
      child: Container(
        child: FloatingActionButton(
          backgroundColor: Colors.white,
          onPressed: () => hide(),
        ),
      ),
    );
  }

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

Это дает вам кнопку, которая вызывает кнопку при нажатии. Нажатие второй кнопки отправляет его вниз. Все это будет полезно, чтобы пользовательские виджеты появлялись вверх и вниз!

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