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

使用phone_form_field时无法预加载circle_flags的SVG离线资源求助

使用phone_form_field时无法预加载circle_flags的SVG离线资源求助

我最近在项目里用phone_number_field包开发手机号输入功能,这个包依赖circle_flags的SVG国旗图标来展示国家/地区标识。之前看circle_flags的文档,它提供了preload函数可以预加载所有国旗资源,我单独写了一段测试代码验证,完全没问题——预加载成功后离线状态下也能正常显示所有国旗,测试代码如下:

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool preloaded = false;
  bool showFlags = false;

  @override
  void initState() {
    super.initState();
    // 预加载国旗以实现即时显示(对web场景尤为有用)
    if (!preloaded) {
      CircleFlag.preload(Flag.values);
      preloaded = true;
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flags'),
        ),
        body: showFlags
            ? ListView.builder(
                itemCount: Flag.values.length,
                itemBuilder: (context, index) => Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: ListTile(
                    leading: CircleFlag(
                      Flag.values[index],
                      size: 32,
                    ),
                    title: Text(Flag.values[index].toString()),
                    onTap: () {},
                  ),
                ),
              )
            : Center(
                child: ElevatedButton(
                  onPressed: () {
                    setState(() {
                      showFlags = true;
                    });
                  },
                  child: const Text('show')),
              ),
      ),
    );
  }
}

但问题来了,当我把预加载逻辑移植到phone_form_field的示例代码中时,预加载完全没生效,而且运行时还会跳转到一个不属于我项目的web_entrypoint.dart文件的断点上。我确认两个场景用的circle_flags版本完全一致,实在搞不懂哪里出了问题,特来求助。我当前出问题的代码(在Google Chrome上运行)如下:

import 'package:flutter/material.dart';
import 'package:phone_form_field/phone_form_field.dart';
import 'package:circle_flags/circle_flags.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  CircleFlag.preload(Flag.values);
  runApp(const MyApp());
}

// 为了展示特性,这个示例用了很多实际场景可能不需要的配置
// 更简洁的示例可以看官方README
class PhoneFieldView extends StatelessWidget {
  static const supportedLocales = [
    Locale('ar'),
    // 目前material不支持
    // Locale('ckb'),
    Locale('de'),
    Locale('el'),
    Locale('en'),
    Locale('es'),
    Locale('fa'),
    Locale('fr'),
    Locale('hi'),
    Locale('hu'),
    Locale('it'),
    // 目前material不支持
    // Locale('ku'),
    Locale('nb'),
    Locale('nl'),
    Locale('pt'),
    Locale('ru'),
    Locale('sv'),
    Locale('tr'),
    Locale('uz'),
    Locale('zh'),
    // ...
  ];

  final PhoneController controller;
  final FocusNode focusNode;
  final CountrySelectorNavigator selectorNavigator;
  final bool withLabel;
  final bool outlineBorder;
  final bool isCountryButtonPersistant;
  final bool mobileOnly;
  final Locale locale;

  const PhoneFieldView({
    Key? key,
    required this.controller,
    required this.focusNode,
    required this.selectorNavigator,
    required this.withLabel,
    required this.outlineBorder,
    required this.isCountryButtonPersistant,
    required this.mobileOnly,
    required this.locale,
  }) : super(key: key);

  PhoneNumberInputValidator? _getValidator(BuildContext context) {
    List<PhoneNumberInputValidator> validators = [];
    if (mobileOnly) {
      validators.add(PhoneValidator.validMobile(context));
    } else {
      validators.add(PhoneValidator.valid(context));
    }
    return validators.isNotEmpty ? PhoneValidator.compose(validators) : null;
  }

  @override
  Widget build(BuildContext context) {
    return AutofillGroup(
      child: Localizations.override(
        context: context,
        locale: locale,
        child: Builder(
          builder: (context) {
            final label = PhoneFieldLocalization.of(context).phoneNumber;
            return PhoneFormField(
              focusNode: focusNode,
              controller: controller,
              isCountryButtonPersistent: isCountryButtonPersistant,
              autofocus: false,
              autofillHints: const [AutofillHints.telephoneNumber],
              countrySelectorNavigator: selectorNavigator,
              decoration: InputDecoration(
                  label: withLabel ? Text(label) : null,
                  border: outlineBorder
                      ? OutlineInputBorder(borderRadius: BorderRadius.circular(50))
                      : const UnderlineInputBorder(),
                  hintText: withLabel ? '' : label,
                  contentPadding: const EdgeInsets.all(0)),
              enabled: true,
              countryButtonStyle: CountryButtonStyle(
                  showFlag: true,
                  showIsoCode: false,
                  showDialCode: true,
                  showDropdownIcon: true,
                  borderRadius: BorderRadius.circular(50)),
              validator: _getValidator(context),
              autovalidateMode: AutovalidateMode.onUserInteraction,
              cursorColor: Theme.of(context).colorScheme.primary,
              // ignore: avoid_print
              onSaved: (p) => print('saved $p'),
              // ignore: avoid_print
              onChanged: (p) => print('change $p'),
            );
          },
        ),
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Phone Form Field Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: const Text('Phone Field Demo')),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: PhoneFieldView(
              controller: PhoneController(null),
              focusNode: FocusNode(),
              selectorNavigator: const CountrySelectorNavigator.bottomSheet(),
              withLabel: true,
              outlineBorder: true,
              isCountryButtonPersistant: true,
              mobileOnly: false,
              locale: const Locale('en'),
            ),
          ),
        ),
      ),
    );
  }
}

有没有朋友遇到过类似的问题?或者能帮我排查下问题出在哪里吗?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:09:37