Flutter年龄选择页图片缩放及切换动画实现需求
Flutter年龄输入页面交互实现方案
核心实现思路
- 用
StatefulWidget维护年龄、当前图片索引、缩放比例状态 - 通过
Slider联动年龄值,实时计算图片缩放比例 - 基于年龄阈值切换图片,切换时触发短暂的缩小回弹动画增强交互感
完整代码示例
import 'package:flutter/material.dart'; class AgeInputPage extends StatefulWidget { const AgeInputPage({super.key}); @override State<AgeInputPage> createState() => _AgeInputPageState(); } class _AgeInputPageState extends State<AgeInputPage> with TickerProviderStateMixin { // 初始年龄 double _currentAge = 20; // 图片索引:0=孩童,1=成人,2=老人 int _currentImageIndex = 1; // 缩放动画控制器 late AnimationController _scaleController; late Animation<double> _scaleAnimation; // 年龄阈值 final int childThreshold = 12; final int elderThreshold = 60; // 基础缩放范围:年龄0对应0.8,年龄100对应1.2 final double minScale = 0.8; final double maxScale = 1.2; @override void initState() { super.initState(); // 初始化缩放动画控制器,用于切换图片时的回弹效果 _scaleController = AnimationController( duration: const Duration(milliseconds: 300), vsync: this, ); _scaleAnimation = Tween<double>(begin: 1.0, end: 1.0).animate( CurvedAnimation(parent: _scaleController, curve: Curves.easeInOut), ); // 初始计算图片索引 _updateImageIndex(_currentAge); } @override void dispose() { _scaleController.dispose(); super.dispose(); } // 根据年龄更新图片索引 void _updateImageIndex(double age) { int newIndex = 1; if (age <= childThreshold) { newIndex = 0; } else if (age >= elderThreshold) { newIndex = 2; } if (newIndex != _currentImageIndex) { setState(() { _currentImageIndex = newIndex; }); // 触发切换时的缩小回弹动画 _triggerSwitchAnimation(); } } // 切换图片时的缩放动画:先缩小到0.7,再恢复到对应年龄的比例 void _triggerSwitchAnimation() { final targetScale = _getScaleFromAge(_currentAge); _scaleController.reset(); _scaleAnimation = TweenSequence([ TweenSequenceItem(tween: Tween<double>(begin: targetScale, end: 0.7), weight: 1), TweenSequenceItem(tween: Tween<double>(begin: 0.7, end: targetScale), weight: 1), ]).animate(CurvedAnimation(parent: _scaleController, curve: Curves.easeInOut)); _scaleController.forward(); } // 根据年龄计算当前基础缩放比例 double _getScaleFromAge(double age) { return minScale + (maxScale - minScale) * (age / 100); } @override Widget build(BuildContext context) { // 如果没有动画在执行,直接用计算的缩放比例;否则用动画值 final currentScale = _scaleController.isAnimating ? _scaleAnimation.value : _getScaleFromAge(_currentAge); return Scaffold( appBar: AppBar(title: const Text('年龄选择')), body: Padding( padding: const EdgeInsets.all(20.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 可缩放切换的图片 AnimatedBuilder( animation: _scaleAnimation, builder: (context, child) { return Transform.scale( scale: currentScale, child: child, ); }, child: _getCurrentImage(), ), const SizedBox(height: 40), // 年龄滑块 Slider( value: _currentAge, min: 0, max: 100, divisions: 100, label: '${_currentAge.toInt()}岁', onChanged: (value) { setState(() { _currentAge = value; }); _updateImageIndex(value); }, ), Text('当前年龄:${_currentAge.toInt()}岁', style: const TextStyle(fontSize: 18)), ], ), ), ); } // 获取当前显示的图片 Widget _getCurrentImage() { const imagePaths = [ // 替换为你的孩童图片路径/AssetImage 'assets/images/child.png', 'assets/images/adult.png', 'assets/images/elder.png', ]; return Image.asset( imagePaths[_currentImageIndex], width: 200, height: 200, fit: BoxFit.contain, ); } }
关键部分说明
- 状态管理:用
_currentAge绑定滑块值,_currentImageIndex控制显示的图片,AnimationController处理切换时的缩放动画 - 图片切换逻辑:
_updateImageIndex方法根据年龄阈值(12岁以下孩童,60岁以上老人)切换图片索引,触发_triggerSwitchAnimation执行回弹效果 - 缩放计算:
_getScaleFromAge将年龄(0-100)映射到0.8-1.2的缩放比例,实现随年龄增大图片放大的效果 - 动画处理:通过
AnimatedBuilder监听缩放动画,Transform.scale应用缩放效果;切换图片时先缩小到0.7再恢复目标比例,增强切换感知
注意事项
- 替换代码中的
imagePaths为你实际的图片资源路径 - 可根据需求调整
minScale、maxScale、年龄阈值以及动画时长,适配不同的交互效果 - 如果使用网络图片,将
Image.asset替换为Image.network即可
内容的提问来源于stack exchange,提问作者Promaster
相关产品推荐
相关产品推荐

