This project demonstrates how to implement the functionality of changing app icons in a Flutter application for both Android and iOS platforms.
Android | iOS |
---|---|
To get started with the examples, clone the repository and navigate to the project directory:
git clone https://github.com/Innim/flutter_app_icon_changer.git
cd flutter_app_icon_changer
Ensure that your icon assets are properly declared in your pubspec.yaml file, so they can be used within your Flutter application.
flutter:
assets:
- assets/icons/
To enable changing app icons in your Android application, follow these steps:
- Modify AndroidManifest.xml: Open the file android/app/src/main/AndroidManifest.xml and add an for each alternate icon you wish to use.
<!-- Main Activity -->
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Alternate Icon 1 -->
<activity-alias
android:name=".MainActivityAlias1"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher1"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<!-- Alternate Icon 2 -->
<activity-alias
android:name=".MainActivityAlias2"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher2"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
Explanation:
- .MainActivityAlias1 and .MainActivityAlias2 are the names of your activity aliases that will be used to switch icons.
- android:icon specifies the icon resource to be displayed.
- android:enabled="false" means the alias is disabled by default and will be enabled programmatically when changing icons.
- Add Alternate Icons: Create new icon files in the android/app/src/main/res/mipmap- folders with the names ic_launcher1.png and ic_launcher2.png. These names should match the android:icon values in your entries.
Example folder structure:
android/app/src/main/res/
mipmap-mdpi/
ic_launcher.png
ic_launcher1.png
ic_launcher2.png
mipmap-hdpi/
ic_launcher.png
ic_launcher1.png
ic_launcher2.png
...
Tips:
- Ensure the icons are of the correct dimensions for each screen density.
- You can use icon generators to simplify this process.
- Update build.gradle (if necessary): Make sure the minimum SDK version is set to 21 or higher in your android/app/build.gradle file:
defaultConfig {
applicationId "com.example.flutter_app_icon_changer"
minSdkVersion 21
targetSdkVersion 33
// ...
}
- Clean and Rebuild the Project: After making these changes, run the following commands:
flutter clean
flutter pub get
flutter run
To enable changing app icons in your iOS application, follow these steps:
- Add Alternate Icons to Assets: Open your project in Xcode:
open ios/Runner.xcworkspace
In Xcode:
- Navigate to Runner/Assets.xcassets.
- Right-click and select New App Icon for each alternate icon you want to add.
- Name the new app icons exactly as specified in your Info.plist (e.g., AppIcon1, AppIcon2).
- Add the icon images of appropriate sizes to each app icon set. Important: The icons must be of the AppIcon type (app icon sets), not regular image sets.
- Modify Info.plist: Open the file ios/Runner/Info.plist and add the alternate icons under the CFBundleIcons key:
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon</string>
</array>
</dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Icon1</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon1</string>
</array>
</dict>
<key>Icon2</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon2</string>
</array>
</dict>
</dict>
</dict>
Explanation:
- CFBundlePrimaryIcon defines the default app icon (AppIcon).
- CFBundleAlternateIcons contains a dictionary of alternate icons.
- Keys Icon1 and Icon2 are identifiers for your alternate icons used in the code.
- CFBundleIconFiles contains an array of icon names corresponding to the sets in Assets.xcassets.
-
Ensure Naming Consistency: Make sure the names in Info.plist match exactly with the icon set names in Assets.xcassets.
-
Rebuild the Project: After making the changes, run:
flutter clean
flutter pub get
flutter run
After setting up the platforms, you can use the icon-changing functionality in your Flutter application.
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_app_icon_changer/flutter_app_icon_changer.dart';
import 'package:flutter_app_icon_changer_example/src/models/models.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _flutterAppIconChangerPlugin = FlutterAppIconChangerPlugin(
iconsSet: CustomIcons.list,
);
CustomIcon _currentIcon = CustomIcons.defaultIcon;
var _isSupported = false;
@override
void initState() {
super.initState();
initPlatformState();
}
Future<void> initPlatformState() async {
_isSupported = await _flutterAppIconChangerPlugin.isSupported();
if (_isSupported) {
final currentIcon = await _flutterAppIconChangerPlugin.getCurrentIcon();
if (!mounted) return;
setState(() {
_currentIcon = CustomIcon.fromString(currentIcon);
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Icon changer example'),
),
body: Column(
children: <Widget>[
const Spacer(),
if (!_isSupported) ...[
const Text('Changing the icon is not supported on this device'),
const SizedBox(height: 8),
],
FittedBox(
child: Opacity(
opacity: _isSupported ? 1 : .5,
child: Padding(
padding:
const EdgeInsetsDirectional.symmetric(horizontal: 24),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildIcon(CustomIcons.redIcon),
const SizedBox(width: 8),
_buildIcon(CustomIcons.purpleIcon),
const SizedBox(width: 8),
_buildIcon(CustomIcons.defaultIcon),
],
),
),
),
),
const Spacer(),
],
),
),
);
}
Widget _buildIcon(CustomIcon icon) {
final border = BorderRadius.circular(8.0);
return InkWell(
borderRadius: border,
onTap: _isSupported ? () => _changeIcon(icon) : null,
child: Card(
shape: icon == _currentIcon ? _buildBorder(border) : null,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: _buildPreviewIcon(
icon,
),
),
),
);
}
OutlinedBorder _buildBorder(BorderRadius borderRadius) {
return RoundedRectangleBorder(
borderRadius: borderRadius,
side: BorderSide(
color: Theme.of(context).primaryColor,
width: 4.0,
),
);
}
Widget _buildPreviewIcon(CustomIcon icon, {double size = 100}) {
return ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.asset(
icon.previewPath,
fit: BoxFit.contain,
width: size,
height: size,
),
);
}
Future<void> _changeIcon(CustomIcon icon) async {
final currentIcon = icon.currentIcon;
try {
await _flutterAppIconChangerPlugin.changeIcon(currentIcon);
setState(() {
_currentIcon = icon;
});
} on PlatformException catch (e) {
debugPrint("Failed to change icon: '${e.message}'.");
}
}
}
Testing on Emulators: Changing app icons may not work on some emulators or simulators. It’s recommended to test on real devices.
Platform Compatibility:
- Android: Requires API level 21 (Android 5.0) or higher.
- iOS: Supported on iOS 10.3 and above.
Permissions:
- No additional permissions are required to change app icons.
Icons Not Changing:
- Verify that the icon names are consistent across your code and configuration files.
- Ensure that the icons are correctly added to the project resources.
Build Errors:
- Run flutter clean and rebuild the project.
- Check for syntax errors in AndroidManifest.xml and Info.plist.
Icon Changing Not Supported:
- Confirm that you are testing on a supported platform.
- Ensure that the minimum SDK version meets the requirements.