2023/10 更新
我觉得我们可以用OpenContainer来改造它。
比使用 Hero 更流畅https://pub.dev/packages/animations https://pub.dev/packages/animations
2023/10 更新
我优化了动画。比之前更顺畅了
2023 版本:https://imgur.com/a/tm7aqEW https://imgur.com/a/tm7aqEW
这是我的解决方案(英雄)。
https://i.stack.imgur.com/y3Na2.jpg https://i.stack.imgur.com/y3Na2.jpg
(抱歉,我无法发布图片,影响我的声誉。)
我自定义了英雄过渡,以尽可能地重新制作应用商店过渡。
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,
);
},
),
接下来,我使用ScaleTransition
and onVerticalDragUpdate
控制弹出动画。
https://i.stack.imgur.com/6iyyR.jpg https://i.stack.imgur.com/6iyyR.jpg
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,
),
),
),
If use Hero
作为动画,需要自定义文本部分的过渡。
Here: https://i.stack.imgur.com/AXHPt.jpg https://i.stack.imgur.com/AXHPt.jpg
就我而言,我通过以下方式控制文本部分转换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,
)),
],
),
),
),
),
虽然它和App Store不一样,但我希望它对你有帮助。
源代码:https://github.com/HelloJunWei/app_store_transition https://github.com/HelloJunWei/app_store_transition
如果您有任何建议,请随时反馈或创建拉取请求。 :)