Fad*_*liS 4 dart flutter flutter-animation flutter-navigation
是否可以使用 Flutter 复制 iOS App Store 的过渡效果?
我尝试通过在两个小部件的根布局中放置两个标签来使用 Hero Animation,但动画看起来很笨拙或不是我所期望的。但好处是我可以在使用 MaterialPageRoute 时向后滑动 iOS。
来源
Hero(
tag: 'heroTag_destinationScreen',
transitionOnUserGestures: true,
flightShuttleBuilder: (BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,) {
final Hero toHero = toHeroContext.widget;
return ScaleTransition(
scale: animation,
child: toHero,
);
},
child: GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
return DestinationScreen()
},
),
);
},
child: Card(
...someCardContent
),
),
)
Run Code Online (Sandbox Code Playgroud)
目的地画面
@override
Widget build(BuildContext context) {
return Hero(
tag: 'heroTag_destinationScreen',
child: Scaffold(
appBar: ...someAppBar
body: ...someMainBodyContent
),
)
}
Run Code Online (Sandbox Code Playgroud)
后来找了一圈,有一个Flutter团队创建的包,可以用container transform来模拟这种效果。我实现了它,效果很好,但后来我无法从左侧进行 iOS 滑动以返回并将布局缩小到卡片视图。
小智 9
这是我的解决方案。
(对不起,我的名声,我不能张贴图片。)
我自定义英雄过渡,以尽可能重新制作应用商店过渡。
child: Hero(
tag: widget.product.id,
child: Image.asset(widget.product.image, fit: BoxFit.cover),
flightShuttleBuilder:
(flightContext, animation, direction, fromcontext, toContext) {
final Hero toHero = toContext.widget;
// Change push and pop animation.
return direction == HeroFlightDirection.push
? ScaleTransition(
scale: animation.drive(
Tween<double>(
begin: 0.75,
end: 1.02,
).chain(
CurveTween(
curve: Interval(0.4, 1.0, curve: Curves.easeInOut)),
),
),
child: toHero.child,
)
: SizeTransition(
sizeFactor: animation,
child: toHero.child,
);
},
),
Run Code Online (Sandbox Code Playgroud)
接下来,我使用ScaleTransition和onVerticalDragUpdate来控制流行动画。
double _initPoint = 0;
double _pointerDistance = 0;
GestureDetector(
onVerticalDragDown: (detail) {
_initPoint = detail.globalPosition.dy;
},
onVerticalDragUpdate: (detail) {
_pointerDistance = detail.globalPosition.dy - _initPoint;
if (_pointerDistance >= 0 && _pointerDistance < 200) {
// scroll up
double _scaleValue = double.parse((_pointerDistance / 100).toStringAsFixed(2));
if (_pointerDistance < 100) {
_closeController.animateTo(_scaleValue,
duration: Duration(milliseconds: 300),
curve: Curves.linear);
}
} else if (_pointerDistance >= 260) {
if (_pop) {
_pop = false;
_closeController.fling(velocity: 1).then((_) {
setState(() {
_heightController.reverse();
});
Timer(Duration(milliseconds: 100), () {
Navigator.of(context).pop();
});
});
}
} else {
// scroll down
}
},
onVerticalDragEnd: (detail) {
if (_pointerDistance >= 550) {
if (_pop) {
_closeController.fling(velocity: 1).then((_) {
setState(() {
_heightController.reverse();
});
Timer(Duration(milliseconds: 100), () {
Navigator.of(context).pop();
});
});
}
} else {
_closeController.fling(velocity: -1);
}
},
child: Hero(
tag: _product.id,
child: Image.asset(
_product.image,
fit: BoxFit.cover,
height: 300,
),
),
),
Run Code Online (Sandbox Code Playgroud)
如果Hero用作动画,则需要自定义文本部分过渡。
在这里:https : //imgur.com/a/gyD6tiZ
就我而言,我通过Sizetransition.
// horizontal way and vertical way.
SizeTransition(
axis: Axis.horizontal,
sizeFactor: Tween<double>(begin: 0.5, end: 1).animate(
CurvedAnimation(
curve: Curves.easeInOut, parent: _widthController),
),
child: SizeTransition(
sizeFactor: Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation(
curve: Curves.easeInOut, parent: _heightController),
),
child: Container(
padding: EdgeInsets.only(
left: 20, right: 20, top: 50, bottom: 30),
width: double.infinity,
color: Colors.white,
constraints: BoxConstraints(
minHeight: 650,
),
child: Column(
// title and text
children: <Widget>[
Text('Title', style: TextStyle(fontSize: 18)),
SizedBox(height: 30),
Text(_text,
style: TextStyle(
fontSize: 15,
)),
],
),
),
),
),
Run Code Online (Sandbox Code Playgroud)
虽然它和 App Store 不一样,但我希望它对你有帮助。
源码:https : //github.com/HelloJunWei/app_store_transition
如果您有任何建议,请随时反馈或创建拉取请求。:)
| 归档时间: |
|
| 查看次数: |
1245 次 |
| 最近记录: |