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

Flutter自定义类方法正确声明及跨类访问问题求助

解决方案

要解决这个问题,我们需要将customBubble方法移到State类中(这样就能访问_animationController),同时通过GlobalKey或静态of方法让外部能获取State实例调用该方法,具体实现如下:

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:floating_action_bubble/floating_action_bubble.dart';

class FabAddCategory extends StatefulWidget {
  final List<Bubble>? items;
  const FabAddCategory({Key? key, this.items}) : super(key: key);

  @override
  _FabAddCategoryState createState() => _FabAddCategoryState();

  // 静态方法:通过上下文获取State实例
  static _FabAddCategoryState? of(BuildContext context) {
    return context.findAncestorStateOfType<_FabAddCategoryState>();
  }
}

class _FabAddCategoryState extends State<FabAddCategory> with SingleTickerProviderStateMixin {
  Animation<double>? _animation;
  AnimationController? _animationController;

  @override
  void initState() {
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 260),
    );
    final curvedAnimation = CurvedAnimation(curve: Curves.easeInOut, parent: _animationController!);
    _animation = Tween<double>(begin: 0, end: 1).animate(curvedAnimation);
    super.initState();
  }

  // 移到State类中的customBubble,可直接访问动画控制器
  Bubble customBubble({
    required IconData icon,
    TextStyle? titleStyle,
    Color? iconColor,
    required String title,
    MaterialColor? bubbleColor,
    required VoidCallback onPress,
  }) {
    return Bubble(
      icon: icon,
      iconColor: iconColor ?? Colors.white,
      title: title,
      titleStyle: titleStyle ?? const TextStyle(fontSize: 16, color: Colors.white),
      bubbleColor: bubbleColor ?? Colors.amber,
      onPress: () {
        // 点击气泡后收起动画
        _animationController?.reverse();
        // 执行外部传入的业务逻辑
        onPress();
      },
    );
  }

  // 单独暴露收起动画的方法,供外部主动调用
  void closeBubbles() {
    _animationController?.reverse();
  }

  @override
  Widget build(BuildContext context) {
    return FloatingActionBubble(
      items: widget.items!,
      animation: _animation!,
      onPress: () => _animationController!.isCompleted
          ? _animationController!.reverse()
          : _animationController!.forward(),
      iconColor: Colors.white,
      backGroundColor: Theme.of(context).primaryColor,
      iconData: Icons.menu,
    );
  }

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

外部调用示例

方式1:通过GlobalKey获取State实例

// 定义全局Key
final fabKey = GlobalKey<_FabAddCategoryState>();

// 在页面中使用FabAddCategory
FabAddCategory(
  key: fabKey,
  items: [
    fabKey.currentState!.customBubble(
      icon: Icons.add,
      title: '新建分类',
      onPress: () {
        // 你的业务逻辑
        print('新建分类触发');
      },
    ),
    fabKey.currentState!.customBubble(
      icon: Icons.delete,
      title: '删除分类',
      onPress: () {
        print('删除分类触发');
      },
    ),
  ],
)

方式2:通过静态of方法获取State实例(适用于子Widget)

// 在子Widget中获取FabAddCategory的State
final fabState = FabAddCategory.of(context);
final newBubble = fabState?.customBubble(
  icon: Icons.edit,
  title: '编辑分类',
  onPress: () {},
);

关键说明

  1. State类中实现customBubble:这样可以直接访问_animationController,解决了无法调用reverse()的问题。
  2. 暴露State实例的方式:通过GlobalKey或静态of方法,让外部能调用State中的customBubble方法,满足复用需求。
  3. 空安全处理:使用?.替代!,避免空指针异常,同时在dispose方法中释放动画控制器,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:25:21