Flutter在线图片画廊横向中心翻页动画实现求助
Flutter 横向中心翻页图片画廊实现
实现思路
核心基于PageView组件,配合PageController控制页面偏移,通过监听页面滚动状态实现自定义动画,让当前图片居中显示,翻页时逐步展示下一张图片,同时添加缩放、位移和透明度过渡提升交互体验。
完整代码实现
1. 画廊组件核心代码
import 'package:flutter/material.dart'; class ImageGallery extends StatefulWidget { final List<String> imagePaths; // 支持本地资源路径或网络图片地址 const ImageGallery({super.key, required this.imagePaths}); @override State<ImageGallery> createState() => _ImageGalleryState(); } class _ImageGalleryState extends State<ImageGallery> { late PageController _pageController; @override void initState() { super.initState(); // 设置viewportFraction让页面宽度小于屏幕,露出两侧部分页面 _pageController = PageController(viewportFraction: 0.85); } @override void dispose() { _pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: Center( child: PageView.builder( controller: _pageController, itemCount: widget.imagePaths.length, itemBuilder: (context, index) => _buildGalleryItem(index), ), ), ); } Widget _buildGalleryItem(int index) { return AnimatedBuilder( animation: _pageController, builder: (context, child) { double animationValue = 1.0; if (_pageController.position.haveDimensions) { // 计算当前页面与滚动偏移的差值 animationValue = _pageController.page! - index; // 处理正负偏移,统一转换为[0,1]区间的动画值 animationValue = (1 - (animationValue.abs() * 0.4)).clamp(0.6, 1.0); // 使用曲线动画让过渡更自然 animationValue = Curves.easeOut.transform(animationValue); } return Transform.translate( // 非当前页向右侧偏移 offset: Offset((1 - animationValue) * 40, 0), child: Opacity( opacity: animationValue, child: SizedBox( // 根据动画值缩放图片容器 height: animationValue * MediaQuery.of(context).size.height * 0.75, width: animationValue * MediaQuery.of(context).size.width * 0.85, child: child, ), ), ); }, child: ClipRRect( borderRadius: BorderRadius.circular(16), child: widget.imagePaths[index].startsWith('http') ? Image.network( widget.imagePaths[index], fit: BoxFit.cover, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return const Center(child: CircularProgressIndicator(color: Colors.white)); }, ) : Image.asset( widget.imagePaths[index], fit: BoxFit.cover, ), ), ); } }
2. 使用示例
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '横向图片画廊', theme: ThemeData.dark(), home: ImageGallery( imagePaths: [ 'https://picsum.photos/800/450?random=1', 'https://picsum.photos/800/450?random=2', 'https://picsum.photos/800/450?random=3', 'https://picsum.photos/800/450?random=4', ], ), ); } }
效果说明
- 当前图片居中显示,占据屏幕大部分区域,圆角处理提升视觉质感
- 翻页时,下一张图片从右侧逐步移入并放大,同时上一张图片逐步缩小并偏移至右侧
- 添加加载状态指示器,优化网络图片加载体验
- 适配本地图片和网络图片两种场景
内容的提问来源于stack exchange,提问作者Dipanjan Das
相关产品推荐
相关产品推荐

