You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 02:05:57