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

Flutter Widget间滑动动画问题:分类切换动画需求及代码求助

Flutter分类切换动画优化方案

我正在开发一款需要实现屏幕动画效果的应用,目前完成了部分开发,但未达到预期效果。需求是:点击分类时,实现选中分类的颜色平滑过渡至目标分类,同时内容从左侧或右侧滑入显示。当前实现代码如下:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: VisitCardCategory.values
      .map((e) => AnimatedBuilder(
          animation: _animationController,
          builder: (context, child) {
            return SlideTransition(
              position: Tween<Offset>(
                begin: Offset(
                    _animationController.value, 0.0),
                end: const Offset(0.0, 0.0),
              ).animate(CurvedAnimation(
                  parent: _animationController,
                  curve: Curves.easeIn)),
              child: FilterWidget(
                onTap: () {
                  filterByCategory(category: e);
                },
                category: e,
                selectedColor: e == selectedCategory
                    ? e.color
                    : Colors.white,
                controller: _animationController,
              ),
            );
          }))
      .toList()),

一、颜色平滑过渡实现

当前代码中颜色直接通过三元表达式切换,无过渡效果。可在FilterWidget内部用AnimatedContainer实现颜色渐变:

class FilterWidget extends StatelessWidget {
  final VisitCardCategory category;
  final bool isSelected;
  final VoidCallback onTap;
  final Color selectedColor;

  const FilterWidget({
    super.key,
    required this.category,
    required this.isSelected,
    required this.onTap,
    required this.selectedColor,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        decoration: BoxDecoration(
          color: isSelected ? selectedColor : Colors.white,
          borderRadius: BorderRadius.circular(8),
        ),
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        child: Text(
          category.name,
          style: TextStyle(
            color: isSelected ? Colors.white : Colors.black,
          ),
        ),
      ),
    );
  }
}

二、内容方向滑入动画优化

当前所有分类的滑动起始偏移量绑定同一个动画控制器值,无法实现左右方向区分。需新增索引判断逻辑,动态设置滑入方向:

// State类中新增变量记录上一个选中分类的索引
int _previousCategoryIndex = 0;

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: VisitCardCategory.values.asMap().entries.map((entry) {
    final index = entry.key;
    final e = entry.value;
    return AnimatedBuilder(
      animation: _animationController,
      builder: (context, child) {
        // 根据索引差判断滑入方向:当前索引大于上一个 → 从右侧滑入,反之从左侧
        final beginOffset = index > _previousCategoryIndex 
            ? const Offset(1.0, 0.0) 
            : const Offset(-1.0, 0.0);
        return SlideTransition(
          position: Tween<Offset>(
            begin: beginOffset,
            end: const Offset(0.0, 0.0),
          ).animate(CurvedAnimation(
            parent: _animationController,
            curve: Curves.easeInOut,
          )),
          child: FilterWidget(
            onTap: () {
              // 更新上一个分类索引
              _previousCategoryIndex = VisitCardCategory.values.indexOf(selectedCategory);
              filterByCategory(category: e);
              // 重置并播放动画
              _animationController.reset();
              _animationController.forward();
            },
            category: e,
            isSelected: e == selectedCategory,
            selectedColor: e.color,
          ),
        );
      },
    );
  }).toList(),
)

三、动画控制器初始化

在State类中正确初始化和销毁控制器:

late AnimationController _animationController;

@override
void initState() {
  super.initState();
  _animationController = AnimationController(
    duration: const Duration(milliseconds: 300),
    vsync: this,
  );
  // 初始化上一个分类索引为当前选中项
  _previousCategoryIndex = VisitCardCategory.values.indexOf(selectedCategory);
}

@override
void dispose() {
  _animationController.dispose();
  super.dispose();
}

关键优化总结

  • 用AnimatedContainer替代直接颜色赋值,实现平滑过渡
  • 通过索引对比动态设置滑入方向,符合原型交互逻辑
  • 每次点击时重置动画控制器,保证切换时动画完整触发

内容的提问来源于stack exchange,提问作者Abhinav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:55:18