You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Flutter应用运行时动态修改应用图标(类似谷歌日历的实现方式)

如何在Flutter应用运行时动态修改应用图标(类似谷歌日历的实现方式)

嘿,这个需求我之前帮不少开发者落地过,得先给你划个重点:Flutter本身没有跨平台的原生API直接修改应用图标,因为应用图标是由iOS/Android系统层面管理的。不过咱们可以借助成熟的第三方插件,配合原生配置来实现——和谷歌日历的逻辑本质一致:提前准备好所有需要的图标资源,再在运行时告诉系统切换到对应图标即可。

下面我用最常用的flutter_dynamic_icon插件一步步拆解实现,涵盖双端配置和Dart代码逻辑:


一、引入核心依赖

首先在你的pubspec.yaml里添加插件依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_dynamic_icon: ^2.1.0 # 版本号以pub.dev上最新版为准

执行flutter pub get拉取依赖到本地。


二、iOS端配置(不能偷懒!)

iOS对应用图标的管控比较严格,所有要切换的图标必须提前打包进App,无法动态生成:

  1. 打开iOS项目(ios/Runner.xcworkspace),在Assets.xcassets中创建多个图标集(比如DateIcon01DateIcon02…),把对应尺寸的图标资源拖入(要覆盖1024x1024、180x180、167x167等所有要求尺寸)。
  2. 打开Info.plist,添加CFBundleAlternateIcons字段,配置每个备选图标的别名和对应图标集:
<key>CFBundleAlternateIcons</key>
<dict>
  <!-- 别名"date_01"对应图标集"DateIcon01" -->
  <key>date_01</key>
  <dict>
    <key>CFBundleIconFiles</key>
    <array>
      <string>DateIcon01</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
  </dict>
  <!-- 继续添加其他日期的图标配置 -->
  <key>date_02</key>
  <dict>
    <key>CFBundleIconFiles</key>
    <array>
      <string>DateIcon02</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
  </dict>
</dict>
  1. 确保CFBundlePrimaryIcon指向你的默认图标集(一般是AppIcon)。

三、Android端配置

Android通过activity-alias(Activity别名)实现图标切换,本质是给主Activity设置多个桌面入口,每个入口对应不同图标:

  1. 打开android/app/src/main/AndroidManifest.xml,在主Activity标签外添加多个activity-alias
<!-- 主Activity(默认图标,保持启用状态) -->
<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTop"
    android:theme="@style/LaunchTheme"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

<!-- 备选图标1:别名date_01 -->
<activity-alias
    android:name=".DateIcon01Activity"
    android:exported="false" <!-- 默认禁用,切换时插件自动启用 -->
    android:icon="@mipmap/date_icon_01"
    android:roundIcon="@mipmap/date_icon_01_round"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>

<!-- 备选图标2:别名date_02 -->
<activity-alias
    android:name=".DateIcon02Activity"
    android:exported="false"
    android:icon="@mipmap/date_icon_02"
    android:roundIcon="@mipmap/date_icon_02_round"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>

火山引擎 最新活动