Как анимировать виджет, когда он становится видимым во флаттере? - PullRequest
0 голосов
/ 23 июня 2018

Я хочу добавить анимацию к некоторым виджетам в моем приложении, но эти виджеты не будут видны, пока пользователь не прокрутит вниз.

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

Есть ли такое событие для прослушивания?Если нет, я думаю, что я могу играть с Viewport или соотношением сторон или MediaQuery?

1 Ответ

0 голосов
/ 23 июня 2018
  1. Создайте GlobalKey и AnimationController для каждого из ваших виджетов.
  2. Используйте ScrollController для прослушивания событий прокрутки в представлении прокрутки (не обязательно должно быть ListView)
  3. Используйте GlobalKey.currentContext.findRenderObject(), чтобы получить ссылку на фактический объект, отображаемый на экране.
  4. Если RenderObject существует, найдите его относительное положение (getTransformTo) и проверьте, видна ли позиция в представлении прокрутки
  5. Запустить анимацию. Чтобы убедиться, что он срабатывает только один раз, проверьте AnimationStatus из AnimationController.

* * Пример 1 022

image

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Playground',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new TestPage(),
    );
  }
}

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => new _TestPageState();
}

class _TestPageState extends State<TestPage> with SingleTickerProviderStateMixin {
  final listViewKey = new GlobalKey();
  final animatedBoxKey = new GlobalKey();

  final scrollController = new ScrollController();

  AnimationController animatedBoxEnterAnimationController;

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

    animatedBoxEnterAnimationController = new AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 2000),
    );

    scrollController.addListener(() {
      _updateAnimatedBoxEnterAnimation();
    });
  }

  static const enterAnimationMinHeight = 100.0;

  _updateAnimatedBoxEnterAnimation() {
    if (animatedBoxEnterAnimationController.status != AnimationStatus.dismissed) {
      return; // animation already in progress/finished
    }

    RenderObject listViewObject = listViewKey.currentContext?.findRenderObject();
    RenderObject animatedBoxObject = animatedBoxKey.currentContext?.findRenderObject();
    if (listViewObject == null || animatedBoxObject == null) return;

    final listViewHeight = listViewObject.paintBounds.height;
    final animatedObjectTop = animatedBoxObject.getTransformTo(listViewObject).getTranslation().y;

    final animatedBoxVisible = (animatedObjectTop + enterAnimationMinHeight < listViewHeight);

    if (animatedBoxVisible) {
      // start animation
      animatedBoxEnterAnimationController.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    final boxOpacity = CurveTween(curve: Curves.easeOut).animate(animatedBoxEnterAnimationController);

    final boxPosition = Tween(begin: Offset(-1.0, 0.0), end: Offset.zero)
        .chain(CurveTween(curve: Curves.elasticOut))
        .animate(animatedBoxEnterAnimationController);

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Flutter Playground'),
      ),
      body: new ListView(
        key: listViewKey,
        controller: scrollController,
        children: <Widget>[
          new Container(
            padding: EdgeInsets.all(16.0),
            child: new Text(
              'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
              style: TextStyle(fontSize: 24.0),
            ),
          ),
          new FadeTransition(
            opacity: boxOpacity,
            child: new SlideTransition(
              position: boxPosition,
              child: new Container(
                key: animatedBoxKey,
                height: 300.0,
                color: Colors.green,
                padding: EdgeInsets.all(16.0),
                child: new Text('Animated Box'),
              ),
            ),
          ),
          new Container(
            padding: EdgeInsets.all(16.0),
            child: new Text(
              'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
              style: TextStyle(fontSize: 24.0),
            ),
          ),
          new FlatButton(
            onPressed: () {
              scrollController.jumpTo(0.0);
              animatedBoxEnterAnimationController.reset();
            },
            child: new Text('Reset'),
          )
        ],
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...