Как правильно использовать SlideTransition? - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь анимировать изображение (или lo go) от центра экрана до верхней экрана.

Для этого я взглянул на SlideTransition. Это работает, но только для портретной ориентации. Когда устройство поворачивается, изображение выходит за пределы экрана. (возможно, я не правильно понял свойство Offset!) Если я заставлю его работать по горизонтали, выходные данные портрета будут изменены.

Позвольте мне показать вам выходные данные:

Портрет:

До анимации

Before Animation

После анимации (Как и хотелось )

After Animation (as wanted)

по горизонтали:

до анимации

Before Animation

После анимации (проблема ЗДЕСЬ)

After Animation (Problem HERE)

Итак, как вы можете видеть, в горизонтальном режиме Lo go выходит из экрана.

Вот код:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

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

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

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _offsetAnimation;

  @override
  void initState() {
    _controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300));

    _offsetAnimation = _controller
        .drive(CurveTween(curve: Curves.easeInOut))
        .drive(Tween<Offset>(begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0)));

    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SlideTransition Demo'),
      ),
      body: Stack(
        children: <Widget>[
          Align(
            alignment: Alignment.center,
            child: SlideTransition(
              position: _offsetAnimation,
              child: FlutterLogo(
                size: 200,
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_controller.status == AnimationStatus.completed) {
            _controller.reverse();
          } else if (_controller.status == AnimationStatus.dismissed) {
            _controller.forward();
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

Ответы [ 2 ]

1 голос
/ 18 марта 2020

SlideTransition делает дробный перевод. И этот перевод зависит от размера дочернего элемента виджета SlideTransition.

Твин (начало: смещение (0,0, 0,0), конец: смещение (0,0, -1,0))

Эта анимация переводит (перемещает) FlutterLogo по оси Y на 200 (высота виджета FlutterLogo)

Tween (начало: смещение (0,0, 0,0) , end: Offset (0.0, -0.5))

Эта анимация движения переводит (перемещает) FlutterLogo по оси Y на 100 (половина высоты виджета FlutterLogo)

Если вы просто хотите анимировать изображение от center до topCenter, тогда вы можете использовать AlignTransition.

Пример :

class FirstPage extends StatefulWidget {
  @override
  FirstPageState createState() => FirstPageState();
}

class FirstPageState extends State<FirstPage> with TickerProviderStateMixin {
  AnimationController _animationController;
  AlignmentGeometryTween _tween;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 3),
    );
    _tween = AlignmentGeometryTween(
      begin: Alignment.center,
      end: Alignment.topCenter,
    );
  }

  TickerFuture _play() {
    _animationController.reset();
    return _animationController.animateTo(
      1.0,
      curve: Curves.easeInOut,
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: Text("Demo")),
        body: AlignTransition(
          alignment: _tween.animate(_animationController),
          child: FlutterLogo(
            size: 200,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.play_arrow),
          onPressed: _play,
        ),
      ),
    );
  }
}

Демо: DartPad

0 голосов
/ 18 марта 2020

Вы можете скопировать и запустить полный код ниже
Вы можете использовать OrientationBuilder и изменить Offset на то, что вам нужно

фрагмент кода

body: OrientationBuilder(
        builder: (context, orientation) {
          if (orientation == Orientation.portrait) {
            _offsetAnimation = _controller
                .drive(CurveTween(curve: Curves.easeInOut))
                .drive(Tween<Offset>(
                    begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0)));
          } else {
            _offsetAnimation = _controller
                .drive(CurveTween(curve: Curves.easeInOut))
                .drive(Tween<Offset>(
                    begin: Offset(0.0, 0.0), end: Offset(-1.0, 0.0)));
          }

работает демо

enter image description here

enter image description here

полный код

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

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

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

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _offsetAnimation;
  Animation<Offset> _offsetAnimationLandscape;

  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 300));

    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SlideTransition Demo'),
      ),
      body: OrientationBuilder(
        builder: (context, orientation) {
          if (orientation == Orientation.portrait) {
            _offsetAnimation = _controller
                .drive(CurveTween(curve: Curves.easeInOut))
                .drive(Tween<Offset>(
                    begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0)));
          } else {
            _offsetAnimation = _controller
                .drive(CurveTween(curve: Curves.easeInOut))
                .drive(Tween<Offset>(
                    begin: Offset(0.0, 0.0), end: Offset(-1.0, 0.0)));
          }
          return Stack(
            children: <Widget>[
              Align(
                alignment: Alignment.center,
                child: SlideTransition(
                  position: _offsetAnimation,
                  child: FlutterLogo(
                    size: 200,
                  ),
                ),
              ),
            ],
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_controller.status == AnimationStatus.completed) {
            _controller.reverse();
          } else if (_controller.status == AnimationStatus.dismissed) {
            _controller.forward();
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}
...