如何在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,无法动态生成:
- 打开iOS项目(
ios/Runner.xcworkspace),在Assets.xcassets中创建多个图标集(比如DateIcon01、DateIcon02…),把对应尺寸的图标资源拖入(要覆盖1024x1024、180x180、167x167等所有要求尺寸)。 - 打开
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>
- 确保
CFBundlePrimaryIcon指向你的默认图标集(一般是AppIcon)。
三、Android端配置
Android通过activity-alias(Activity别名)实现图标切换,本质是给主Activity设置多个桌面入口,每个入口对应不同图标:
- 打开
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"/>




