如何正确使用SlideTransition?

时间:2020-03-18 02:20:08

标签: flutter flutter-animation

我正在尝试使图像(或徽标)从屏幕的中心到屏幕的顶部

为此,我看了SlideTransition。它有效,但仅用于纵向方向。旋转设备时,图像会超出屏幕。 (也许我无法正确理解Offset属性!)如果我将其用于水平,则肖像的输出将发生更改。

让我向您展示输出:

肖像:

动画之前

Before Animation

动画后(根据需要)

After Animation (as wanted)

水平

动画之前

Before Animation

动画后(问题在这里)

After Animation (Problem 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;

  @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 个答案:

答案 0 :(得分:1)

SlideTransition执行小数转换。而且此翻译取决于SlideTransition小部件的子级大小。

补间(开始:偏移(0.0,0.0),结束:偏移(0.0,-1.0))

此补间在y轴上平移(移动)FlutterLogo 200(FlutterLogo小部件的高度)

补间(开始:偏移(0.0,0.0),结束:偏移(0.0,-0.5))

此补间在y轴上平移(移动)FlutterLogo 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

答案 1 :(得分:0)

您可以在下面复制粘贴运行完整代码
您可以使用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),
      ),
    );
  }
}