如何正确使用 SlideTransition?
How to use SlideTransition properly?
我正在尝试从屏幕的 center 到屏幕的 top 动画图像(或徽标)。
为此,我查看了 SlideTransition
。它有效,但仅适用于纵向。旋转设备时,图像会超出屏幕范围。 (也许我没有正确理解 Offset
属性!)如果我让它在水平方向上工作,肖像的输出就会改变。
让我向您展示输出:
纵向:
动画前
动画后(随心所欲)
水平:
动画前
动画后 (这里有问题)
因此,如您所见,在水平模式下,徽标会超出屏幕范围。
代码如下:
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),
),
);
}
}
您可以复制粘贴 运行 下面的完整代码
您可以使用 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)));
}
工作演示
完整代码
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),
),
);
}
}
SlideTransition
进行分数翻译。并且此翻译取决于 SlideTransition
小部件的子项的大小。
Tween(begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0))
此补间在 y 轴上平移(移动)FlutterLogo
200(FlutterLogo
小部件的高度)
Tween(begin: Offset(0.0, 0.0), end: Offset(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
我正在尝试从屏幕的 center 到屏幕的 top 动画图像(或徽标)。
为此,我查看了 SlideTransition
。它有效,但仅适用于纵向。旋转设备时,图像会超出屏幕范围。 (也许我没有正确理解 Offset
属性!)如果我让它在水平方向上工作,肖像的输出就会改变。
让我向您展示输出:
纵向:
动画前
动画后(随心所欲)
水平:
动画前
动画后 (这里有问题)
因此,如您所见,在水平模式下,徽标会超出屏幕范围。
代码如下:
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),
),
);
}
}
您可以复制粘贴 运行 下面的完整代码
您可以使用 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)));
}
工作演示
完整代码
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),
),
);
}
}
SlideTransition
进行分数翻译。并且此翻译取决于 SlideTransition
小部件的子项的大小。
Tween(begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0))
此补间在 y 轴上平移(移动)FlutterLogo
200(FlutterLogo
小部件的高度)
Tween(begin: Offset(0.0, 0.0), end: Offset(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