flutter - How to create sticky shop button animation in Flutter?
问题描述
How can I create this sticky buy button animation of Adidas app in Flutter. I have tried to use a scroll controller to listen for the position of user and then use an animated container but it is of no use since I have to define my scroll controller in my initstate while the height of my containers are relative to my device's height. here is the link of video for the animation: https://drive.google.com/file/d/1TzIUBr6abRQI87xAVu4NOPG67aftzceK/view?usp=sharing
this is what the widget tree looks like:
Scaffold(appbar,FAB,_body),
_body= SingleChildSrollView child:Column[Container(child:Listview)
,Container(child:PageView(children:[GridView])
,Container
,Container(this is where the shop button should be, the one that replaces the FAB)
,GridView,])
解决方案
Output:
void main() => runApp(MaterialApp(home: Scaffold(body: HomePage(), appBar: AppBar())));
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
ScrollController _controller = ScrollController();
double _boxHeight = 200, _screenHeight;
int _itemIndex = 5;
bool _itemVisibility = true;
@override
void initState() {
super.initState();
double offsetEnd;
WidgetsBinding.instance.addPostFrameCallback((_) {
RenderBox box = context.findRenderObject();
_screenHeight = box.globalToLocal(Offset(0, MediaQuery.of(context).size.height)).dy;
offsetEnd = ((_itemIndex + 1) - (_screenHeight / _boxHeight)) * _boxHeight;
});
_controller.addListener(() {
if (_controller.position.pixels >= offsetEnd) {
if (_itemVisibility) setState(() => _itemVisibility = false);
} else {
if (!_itemVisibility) setState(() => _itemVisibility = true);
}
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ListView.builder(
controller: _controller,
itemCount: 8,
itemBuilder: (context, index) {
return _buildBox(
index: index,
color: index == _itemIndex ? Colors.cyan : Colors.blue[((index + 1) * 100) % 900],
);
},
),
Positioned(
bottom: 0,
right: 0,
left: 0,
child: Visibility(
visible: _itemVisibility,
child: _buildBox(index: _itemIndex, color: Colors.cyan),
),
),
],
);
}
Widget _buildBox({int index, Color color}) {
return Container(
height: _boxHeight,
color: color,
alignment: Alignment.center,
child: Text(
"${index}",
style: TextStyle(fontSize: 52, fontWeight: FontWeight.bold),
),
);
}
}
推荐阅读
- angular - Angular 6 Ngx typeahead 选项渲染
- google-cloud-platform - 如何仅从我的帐户内部 IP 地址授予对我的 GCP 实例之一的访问权限
- javascript - 如何将 spring.bind 变量从 freemaker 传递给 javascript 函数
- java - 维护链表插入的顺序
- google-chrome - 我可以使用 SVG 工具栏图标吗?
- python-3.x - 如何将聊天机器人用于多个标签
- javascript - 如何在 Angular 7 打字稿中使用 isNaN 和 charAt?
- knex.js - 在`.increment()`方法之后是否有必要使用`.primary()`方法?
- r - 矩阵的值分配在 r 中不起作用
- java - 无法在java中将comp 3解压缩为数字