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

Flutter中如何实时监听Signature签名板是否为空?

Flutter signature 5.4.1 实时监听签名状态问题解决

问题描述

使用signature 5.4.1包时,调用_controller.isNotEmpty()或_controller.isEmpty()无法实时获取签名板的状态变化——只有应用完全刷新时,这两个方法的返回值才会更新。目前只能通过ValueListenableBuilder结合自定义ValueNotifier实现监听,但官方示例未覆盖该场景。

解决方案

优化现有实现(快速解决)

当前代码仅在onDrawEnd时更新状态,缺少清除签名时的同步逻辑。可以通过控制器的回调和清除操作同步维护ValueNotifier状态,确保实时性:

class TestSignature extends StatefulWidget {
  @override
  State<TestSignature> createState() => _TestSignatureState();
}

class _TestSignatureState extends State<TestSignature> {
  final ValueNotifier<bool> _hasSignature = ValueNotifier<bool>(false);
  final SignatureController _controller = SignatureController(
    penStrokeWidth: 2.0,
    penColor: AppTheme.colorBrand0,
    exportBackgroundColor: Colors.transparent,
    exportPenColor: AppTheme.colorBrand0,
  );

  @override
  void initState() {
    super.initState();
    // 绘制开始时标记已有签名
    _controller.onDrawStart = () => _hasSignature.value = true;
    // 绘制结束时校验实际状态(避免空笔画)
    _controller.onDrawEnd = () => _hasSignature.value = _controller.isNotEmpty();
  }

  @override
  void dispose() {
    _controller.dispose();
    _hasSignature.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ValueListenableBuilder<bool>(
          valueListenable: _hasSignature,
          builder: (context, hasSignature, child) {
            return Column(
              children: [
                Signature(
                  key: const Key('signature'),
                  controller: _controller,
                  height: 150,
                  backgroundColor: AppTheme.colorBrand1,
                ),
                // 示例:根据状态启用/禁用清除按钮
                ElevatedButton(
                  onPressed: hasSignature 
                      ? () {
                          _controller.clear();
                          _hasSignature.value = false;
                        } 
                      : null,
                  child: const Text('清除签名'),
                ),
              ],
            );
          },
        ),
      ],
    );
  }
}

为什么原方法无法实时更新?

signature 5.4.1的SignatureController中,isEmpty()和isNotEmpty()是直接计算当前路径数量的同步方法,没有绑定可监听状态。当用户绘制或清除时,控制器内部状态变化不会主动通知UI刷新,只有Widget树重建时才会重新计算返回值。

进阶方案:扩展控制器实现可监听状态

如果需要更简洁的调用方式,可以扩展SignatureController,将签名状态封装为内置的ValueNotifier:

class ListenableSignatureController extends SignatureController {
  final ValueNotifier<bool> _isEmpty = ValueNotifier<bool>(true);

  ValueListenable<bool> get isEmptyListenable => _isEmpty;

  ListenableSignatureController({
    super.penStrokeWidth,
    super.penColor,
    super.exportBackgroundColor,
    super.exportPenColor,
  }) {
    // 重写绘制回调同步状态
    super.onDrawStart = () => _isEmpty.value = false;
    super.onDrawEnd = () => _isEmpty.value = super.isEmpty();
  }

  @override
  void clear() {
    super.clear();
    _isEmpty.value = true;
  }

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

使用时直接监听控制器的内置状态:

final _controller = ListenableSignatureController(
  penStrokeWidth: 2.0,
  penColor: AppTheme.colorBrand0,
);

// 在build方法中
ValueListenableBuilder<bool>(
  valueListenable: _controller.isEmptyListenable,
  builder: (context, isEmpty, child) {
    return Column(
      children: [
        Signature(controller: _controller, height: 150),
        Text(isEmpty ? '未签名' : '已签名'),
      ],
    );
  },
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:59:07