flutter_easy

flutter_easy

pub flutter license build

A common Flutter package. Example

HarmonyOS

example 已在 HarmonyOS 5.1.0 / API 18 ARM64 模拟器验证构建、安装、启动、图片与文件选择、 图片预览和颜色提取、URL 跳转、系统分享面板及网络状态读取。 使用 Flutter OH 3.41.10-ohos-1.0.1(Dart 3.11.5)。

鸿蒙应用需要在自己的 pubspec.yaml 中额外添加以下平台实现,保留原有的 flutter_easy 依赖。平台实现由应用显式声明,example 的鸿蒙专用依赖不会传递给使用者的应用。

dependencies:
  # 鸿蒙存储、目录、应用信息和设备信息实现
  shared_preferences_ohos: 2.2.0
  path_provider_ohos: 2.2.1
  package_info_plus_harmonyos: 0.0.1
  device_info_plus_harmonyos: 0.0.5

  # 使用 URL 打开/检测功能时添加;完整 example 需要此项
  url_launcher_ohos: ^6.3.0

这些版本与当前 flutter_easy 的依赖组合一起通过验证;升级任一相关包后需重新验证兼容性。 其中应用信息和设备信息适配包要求 Flutter ≥3.27、Dart ≥3.6.2,Flutter 3.24.5 无法解析此依赖组合。 鸿蒙构建和运行必须使用 Flutter OH;上游标准 Flutter SDK 不能代替 Flutter OH 构建 ohos/ 工程。

添加依赖后,使用 Flutter OH 执行 flutter pub get 和鸿蒙构建命令,由工具生成平台插件注册文件。 业务代码继续使用原有插件 API,无需手动修改生成的注册文件。这些适配包只声明 ohos 平台, Android/iOS 继续使用原有平台实现;但新增依赖的 SDK 版本约束对整个应用都生效。

example 已额外接入网络状态、分享、图片和文件选择的现成鸿蒙实现,配置集中在 example/ohos/scripts/harmony_overrides.yaml。使用主包的应用仍需自行配置这些平台实现, 它们不会随 example 传递。完整 example 依赖需要 Flutter OH ≥3.41 / Dart ≥3.11; 分享使用已适配的 share_plus Git 版本,仅在鸿蒙隔离工程中覆盖依赖。 运行流程见 example 鸿蒙运行说明。

仓库内的 example 已隔离普通平台与鸿蒙的 SDK、依赖和缓存。标准 Flutter 3.44.9 继续用于普通平台; 在仓库根目录执行 example/ohos/build_ohos 一键构建鸿蒙,DevEco 直接打开 example/ohos/。 鸿蒙辅助脚本及专用依赖集中在 example/ohos/scripts/,不覆盖普通平台的锁文件和包解析配置。

主包提供 isOhos 判断鸿蒙原生平台,标准 Flutter SDK 也可以编译。isPhone、isTablet 包含鸿蒙,平板仍以逻辑短边 ≥600 判断;isDesktop 只匹配 macOS、Windows、Linux。 跨平台布局可用 hasBottomSafeArea 判断底部安全区;isIPhoneX 仅表示带底部安全区的 iPhone, 不匹配鸿蒙、Android 或 iPad,也不用于识别具体 iPhone 型号。 isWebInOhos 判断鸿蒙浏览器,isWebInMobile 包含鸿蒙手机和平板浏览器,不包含鸿蒙 PC 浏览器。 浏览器识别依据见华为 User-Agent 说明。

接入上述设备信息实现后,DeviceInfoUtil.init() 会从已有插件返回的数据中填充设备型号、品牌、 名称、系统版本和真机标识。主包不额外引入鸿蒙插件依赖。BasePopScope 默认覆盖 Android 和鸿蒙的系统返回拦截,保留原有 onlyAndroid 参数名以兼容现有调用。 appStoreUrl 及评价链接在鸿蒙使用本机包名生成 AppGallery 详情链接,格式遵循 华为应用市场说明。 原有 checkVersion 只处理 Android APK / iOS IPA,不在鸿蒙发起错误平台的版本检查。

onLaunch(url) 在鸿蒙默认使用系统浏览器或对应应用打开,继续调用已有 url_launcher_ohos 实现。显式传入 inAppWebView / inAppBrowserView 时,需要按照插件说明在宿主配置 WebView 页面、路由及 webViewConfiguration.headers['harmony_browser_page']。

Getting Started

Additional arguments:

--dart-define=app-debug-flag=true

Run:

flutter run --release --dart-define=app-debug-flag=true

Example:

main.dart

void main() async {
  await initEasyApp(
    appBaseURLChangedCallback: () {
      // Reload API
      configAPI(null);
    },
  );
  await initApp();
  runApp(const MyApp());
  if (isAndroid) {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    // Set overlay style status bar. It must run after MyApp(), because MaterialApp may override it.
    SystemUiOverlayStyle systemUiOverlayStyle =
        const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
  }
}

app.dart

Future<void> initApp() async {
  // Encrypt password
  StorageUtil.setEncrypt("XxXxXxXxXxXxXxXxX");
  // Load user info
  await Get.putAsync(() => UserService().load());
  // Load API
  configAPI(null);
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BaseApp(
      initialRoute: Routes.splash,
      getPages: Routes.routes,
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        LocaleNamesLocalizationsDelegate(),
      ],
      supportedLocales: S.delegate.supportedLocales,
      locale: Get.deviceLocale,
      localeResolutionCallback:
          (Locale? locale, Iterable<Locale> supportedLocales) {
        logDebug("localeResolutionCallback: $locale");
        if (locale == null || !S.delegate.isSupported(locale)) {
          return null;
        }
        if (locale.languageCode == "zh") {
          return const Locale("zh", "CN");
        }
        return locale;
      },
    );
  }
}

routes.dart

class Routes {
  static final String root = '/';
  static final String splash = '/splash';

  Routes._();

  static final List<GetPage> routes = [
    GetPage(
      name: Routes.root,
      page: () => RootPage(),
    ),
    GetPage(
      name: Routes.splash,
      page: () => SplashPage(),
    ),
    GetPage(
      name: routesLoginNamed,
      page: () => LoginPage(),
    ),
}

Installing

Add flutter_easy to your pubspec.yaml file:

dependencies:
  flutter_easy:

Import flutter_easy in files that it will be used:

import 'package:flutter_easy/flutter_easy.dart';

Libraries

components/export
components/src/base
components/src/base64_image
components/src/base_animation_image
components/src/base_animation_number_text
components/src/base_cycle_view
components/src/base_example_view
components/src/base_expandable_text
components/src/base_history_mixin
components/src/base_keep_alive
components/src/base_loading_view
components/src/base_navigator_pop_exit
components/src/base_placeholder_view
components/src/base_progress_bar
components/src/base_refresh
components/src/base_resizable_view
components/src/base_segment_bar
components/src/base_shimmer
components/src/base_sliver_expanded
components/src/base_sliver_persistent_header
components/src/base_state
components/src/base_tab_page
components/src/base_tab_state_controller
components/src/base_tag_list_view
components/src/base_web_image
configs/export
configs/src/base_default_config
configs/src/base_picker_config
extension/export
extension/src/date_time_extension
extension/src/duration_extensions
extension/src/dynamic_extensions
extension/src/font_extensions
extension/src/function_extensions
extension/src/list_extension
extension/src/map_extensions
extension/src/num_extensions
extension/src/string_extensions
extension/src/widget_extension
flutter_easy
routes/routes
utils/export
utils/src/adapt_util
utils/src/color_util
utils/src/connectivity_util
utils/src/crypto_util
utils/src/date_picker_util
utils/src/date_util
utils/src/device_info_util
utils/src/docx_util
utils/src/formatter_util
utils/src/global_util
utils/src/hw/hw_html
utils/src/hw/hw_io
utils/src/hw/hw_mp
https://dart.dev/guides/libraries/create-library-packages
utils/src/hw/hw_none
utils/src/image_util
utils/src/intl_util
utils/src/json_util
utils/src/loading_util
utils/src/locale_util
utils/src/logger/log_backend
utils/src/logger/log_backend_factory
utils/src/logger/log_backend_factory_io
utils/src/logger/log_backend_factory_stub
utils/src/logger_util
utils/src/lunar/lunar_solar_converter
utils/src/multi_data_picker_util
utils/src/network_util
utils/src/package_info_util
utils/src/password_util
utils/src/picker/base/base_picker
utils/src/picker/base/base_picker_cliprrect
utils/src/picker/base/base_picker_title
utils/src/picker/base/base_picker_title_config
utils/src/picker/base_multi_data_picker
utils/src/picker/time_picker/base_date_picker_constants
utils/src/picker/time_picker/base_date_time_formatter
utils/src/picker/time_picker/date_picker/base_date_picker
utils/src/picker/time_picker/date_picker/base_date_widget
utils/src/picker/time_picker/date_picker/base_datetime_widget
utils/src/picker/time_picker/date_picker/base_time_widget
utils/src/picker/time_picker/date_range_picker/base_date_range_picker
utils/src/picker/time_picker/date_range_picker/base_date_range_side_widget
utils/src/picker/time_picker/date_range_picker/base_date_range_widget
utils/src/picker/time_picker/date_range_picker/base_time_range_side_widget
utils/src/picker/time_picker/date_range_picker/base_time_range_widget
utils/src/share_util
utils/src/shared_preferences_util
utils/src/storage_util
utils/src/string_util
utils/src/text_paginate_util
utils/src/timer_util
utils/src/toast_util
utils/src/uuid_util
utils/src/vendor_util