Skip to content

Commit 44aefc9

Browse files
committed
Merge branch 'master' into misc/migrate-away-from-deprecated-strong-mode-options
2 parents 1528586 + 3705b51 commit 44aefc9

24 files changed

+687
-287
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# Changelog
22

3+
## 0.14.0 (21st September 2024)
4+
5+
- Android: Support for monochrome icons [#563](https://github.com/fluttercommunity/flutter_launcher_icons/pull/563)
6+
7+
**Before**
8+
9+
<img src="https://github.com/user-attachments/assets/ce16287d-1394-4404-b056-8308f0a69f07" width=40%>
10+
11+
**Now**
12+
13+
<img src="https://github.com/user-attachments/assets/a420fefd-28b0-4eb9-8fd0-2e03068d3d83" width=40%>
14+
15+
- Android: Ability to set inset for adaptive icon foreground and monochrome icon [#563](https://github.com/fluttercommunity/flutter_launcher_icons/pull/563)
16+
- iOS: Dark and Tinted icons for iOS 18+ [#569](https://github.com/fluttercommunity/flutter_launcher_icons/pull/569)
17+
318
## 0.13.1 (15th April 2023)
419

520
- Can now use `flutter_launcher_icons` instead of `flutter_icons` [#478](https://github.com/fluttercommunity/flutter_launcher_icons/pull/478)

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ A command-line tool which simplifies the task of updating your Flutter app's lau
1313
Run the following command to create a new config automatically:
1414

1515
```shell
16-
flutter pub run flutter_launcher_icons:generate
16+
dart run flutter_launcher_icons:generate
1717
```
1818

1919
This will create a new file called `flutter_launcher_icons.yaml` in your `flutter` project's root directory.
2020

2121
If you want to override the default location or name of the config file, use the `-f` flag:
2222

2323
```shell
24-
flutter pub run flutter_launcher_icons:generate -f <your config file name here>
24+
dart run flutter_launcher_icons:generate -f <your config file name here>
2525
```
2626

2727
To override an existing config file, use the `-o` flag:
2828

2929
```shell
30-
flutter pub run flutter_launcher_icons:generate -o
30+
dart run flutter_launcher_icons:generate -o
3131
```
3232

3333
OR
@@ -37,7 +37,7 @@ An example is shown below. More complex examples [can be found in the example pr
3737

3838
```yaml
3939
dev_dependencies:
40-
flutter_launcher_icons: "^0.13.1"
40+
flutter_launcher_icons: ^0.14.0
4141

4242
flutter_launcher_icons:
4343
android: "launcher_icon"
@@ -105,6 +105,9 @@ Shown below is the full list of attributes which you can specify within your Flu
105105
be used to fill out the background of the adaptive icon.
106106
- `adaptive_icon_foreground`: The image asset which will be used for the icon foreground of the adaptive icon
107107
*Note: Adaptive Icons will only be generated when both adaptive_icon_background and adaptive_icon_foreground are specified. (the image_path is not automatically taken as foreground)*
108+
- `adaptive_icon_foreground_inset`: This is used to add padding to the icon when applying an adaptive icon. The default value is `16`.
109+
- `adaptive_icon_monochrome`: The image asset which will be used for the icon
110+
foreground of the Android 13+ themed icon. For more information see [Android Adaptive Icons](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive#user-theming)
108111

109112
### IOS
110113

@@ -114,27 +117,30 @@ be used to fill out the background of the adaptive icon.
114117
- `icon/path/here.png`: This will generate a new launcher icons for the platform with the name you specify, without removing the old default existing Flutter launcher icon.
115118
- `image_path_ios`: The location of the icon image file specific for iOS platform (optional - if not defined then the image_path is used)
116119
- `remove_alpha_ios`: Removes alpha channel for IOS icons
120+
- `image_path_ios_dark_transparent`: The location of the dark mode icon image file specific for iOS 18+ platform. *Note: Apple recommends this icon to be transparent. For more information see [Apple Human Interface Guidelines for App Icons](https://developer.apple.com/design/human-interface-guidelines/app-icons#iOS-iPadOS)*
121+
- `image_path_ios_tinted_grayscale`: The location of the tinted mode icon image file specific for iOS 18+ platform. *Note: This icon should be an grayscale image. Use `desaturate_tinted_to_grayscale_ios: true` to automatically desaturate the image provided here.*
122+
- `desaturate_tinted_to_grayscale_ios`: Automatically desaturates tinted mode icon image to grayscale, *defaults to false*
117123
- `background_color_ios`: The color (in the format "#RRGGBB") to be used as the background when removing the alpha channel. It is used only when the `remove_alpha_ios` property is set to true. (optional - if not defined then `#ffffff` is used)
118124

119125
### Web
120126

121127
- `web`: Add web related configs
122-
- `generate`: Specifies weather to generate icons for this platform or not
128+
- `generate`: Specifies whether to generate icons for this platform or not
123129
- `image_path`: Path to web icon.png
124130
- `background_color`: Updates *background_color* in `web/manifest.json`
125131
- `theme_color`: Updates *theme_color* in `web/manifest.json`
126132

127133
### Windows
128134

129135
- `windows`: Add Windows related configs
130-
- `generate`: Specifies weather to generate icons for Windows platform or not
136+
- `generate`: Specifies whether to generate icons for Windows platform or not
131137
- `image_path`: Path to web icon.png
132138
- `icon_size`: Windows app icon size. Icon size should be within this constrains *48<=icon_size<=256, defaults to 48*
133139

134140
### MacOS
135141

136142
- `macos`: Add MacOS related configs
137-
- `generate`: Specifies weather to generate icons for MacOS platform or not
143+
- `generate`: Specifies whether to generate icons for MacOS platform or not
138144
- `image_path`: Path to macos icon.png file
139145

140146
*Note: iOS icons should [fill the entire image](https://stackoverflow.com/questions/26014461/black-border-on-my-ios-icon) and not contain transparent borders.*

analysis_options.yaml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ analyzer:
1111
missing_return: warning
1212
# allow having TODOs in the code
1313
todo: ignore
14-
# Ignore analyzer hints for updating pubspecs when using Future or
15-
# Stream and not importing dart:async
16-
# Please see https://github.com/flutter/flutter/pull/24528 for details.
17-
sdk_version_async_exported_from_core: ignore
1814
exclude:
1915
- "bin/cache/**"
2016
# the following two are relative to the stocks example and the flutter package respectively
@@ -58,10 +54,9 @@ linter:
5854
- flutter_style_todos
5955
- hash_and_equals
6056
- implementation_imports
61-
- iterable_contains_unrelated_type
57+
- collection_methods_unrelated_type
6258
- library_names
6359
- library_prefixes
64-
- list_remove_unrelated_type
6560
- no_adjacent_strings_in_list
6661
- no_duplicate_case_values
6762
- non_constant_identifier_names

bin/generate.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,14 @@ flutter_launcher_icons:
9191
min_sdk_android: 21 # android min sdk min:16, default 21
9292
# adaptive_icon_background: "assets/icon/background.png"
9393
# adaptive_icon_foreground: "assets/icon/foreground.png"
94+
# adaptive_icon_monochrome: "assets/icon/monochrome.png"
9495
9596
ios: true
9697
# image_path_ios: "assets/icon/icon.png"
9798
remove_alpha_channel_ios: true
99+
# image_path_ios_dark_transparent: "assets/icon/icon_dark.png"
100+
# image_path_ios_tinted_grayscale: "assets/icon/icon_tinted.png"
101+
# desaturate_tinted_to_grayscale_ios: true
98102
99103
web:
100104
generate: true
8.23 KB
Loading

example/default_example/pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ flutter_launcher_icons:
2121
ios: true # can specify file name here e.g. "My-Launcher-Icon"
2222
adaptive_icon_background: "assets/images/christmas-background.png" # only available for Android 8.0 devices and above
2323
adaptive_icon_foreground: "assets/images/icon-foreground-432x432.png" # only available for Android 8.0 devices and above
24+
adaptive_icon_foreground_inset: 16 # only available for Android 8.0 devices and above
25+
adaptive_icon_monochrome: "assets/images/icon-monochrome-432x432.png" # only available for Android 13 devices and above
2426
min_sdk_android: 21 # android min sdk min:16, default 21
2527
remove_alpha_ios: true
2628
background_color_ios: "#ffffff"

lib/android.dart

Lines changed: 83 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,93 @@ void createAdaptiveIcons(
123123
flavor,
124124
);
125125
} else {
126-
createAdaptiveIconMipmapXmlFile(config, flavor);
127126
updateColorsXmlFile(backgroundConfig, flavor);
128127
}
129128
}
130129

130+
void createAdaptiveMonochromeIcons(
131+
Config config,
132+
String? flavor,
133+
) {
134+
utils.printStatus('Creating adaptive monochrome icons Android');
135+
136+
// Retrieve the necessary Flutter Launcher Icons configuration from the pubspec.yaml file
137+
final String? monochromeImagePath = config.adaptiveIconMonochrome;
138+
if (monochromeImagePath == null) {
139+
throw const InvalidConfigException(errorMissingImagePath);
140+
}
141+
final Image? monochromeImage = utils.decodeImageFile(monochromeImagePath);
142+
if (monochromeImage == null) {
143+
return;
144+
}
145+
146+
// Create adaptive icon monochrome images
147+
for (AndroidIconTemplate androidIcon in adaptiveForegroundIcons) {
148+
overwriteExistingIcons(
149+
androidIcon,
150+
monochromeImage,
151+
constants.androidAdaptiveMonochromeFileName,
152+
flavor,
153+
);
154+
}
155+
}
156+
157+
void createMipmapXmlFile(
158+
Config config,
159+
String? flavor,
160+
) {
161+
utils.printStatus('Creating mipmap xml file Android');
162+
163+
String xmlContent = '';
164+
165+
if (config.hasAndroidAdaptiveConfig) {
166+
if (isAdaptiveIconConfigPngFile(config.adaptiveIconBackground!)) {
167+
xmlContent +=
168+
' <background android:drawable="@drawable/ic_launcher_background"/>\n';
169+
} else {
170+
xmlContent +=
171+
' <background android:drawable="@color/ic_launcher_background"/>\n';
172+
}
173+
174+
xmlContent += '''
175+
<foreground>
176+
<inset
177+
android:drawable="@drawable/ic_launcher_foreground"
178+
android:inset="${config.adaptiveIconForegroundInset}%" />
179+
</foreground>
180+
''';
181+
}
182+
183+
if (config.hasAndroidAdaptiveMonochromeConfig) {
184+
xmlContent += '''
185+
<monochrome>
186+
<inset
187+
android:drawable="@drawable/ic_launcher_monochrome"
188+
android:inset="${config.adaptiveIconForegroundInset}%" />
189+
</monochrome>
190+
''';
191+
}
192+
193+
late File mipmapXmlFile;
194+
if (config.isCustomAndroidFile) {
195+
mipmapXmlFile = File(
196+
constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml',
197+
);
198+
} else {
199+
mipmapXmlFile = File(
200+
constants.androidAdaptiveXmlFolder(flavor) +
201+
constants.androidDefaultIconName +
202+
'.xml',
203+
);
204+
}
205+
206+
mipmapXmlFile.create(recursive: true).then((File adaptiveIconFile) {
207+
adaptiveIconFile.writeAsString(
208+
xml_template.mipmapXmlFile.replaceAll('{{CONTENT}}', xmlContent),
209+
);
210+
});
211+
}
212+
131213
/// Retrieves the colors.xml file for the project.
132214
///
133215
/// If the colors.xml file is found, it is updated with a new color item for the
@@ -151,29 +233,6 @@ void updateColorsXmlFile(String backgroundConfig, String? flavor) {
151233
}
152234
}
153235

154-
/// Creates the xml file required for the adaptive launcher icon
155-
/// FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml
156-
void createAdaptiveIconMipmapXmlFile(
157-
Config config,
158-
String? flavor,
159-
) {
160-
if (config.isCustomAndroidFile) {
161-
File(
162-
constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml',
163-
).create(recursive: true).then((File adaptiveIcon) {
164-
adaptiveIcon.writeAsString(xml_template.icLauncherXml);
165-
});
166-
} else {
167-
File(
168-
constants.androidAdaptiveXmlFolder(flavor) +
169-
constants.androidDefaultIconName +
170-
'.xml',
171-
).create(recursive: true).then((File adaptiveIcon) {
172-
adaptiveIcon.writeAsString(xml_template.icLauncherXml);
173-
});
174-
}
175-
}
176-
177236
/// creates adaptive background using png image
178237
void _createAdaptiveBackgrounds(
179238
Config config,
@@ -196,24 +255,6 @@ void _createAdaptiveBackgrounds(
196255
flavor,
197256
);
198257
}
199-
200-
// Creates the xml file required for the adaptive launcher icon
201-
// FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml
202-
if (config.isCustomAndroidFile) {
203-
File(
204-
constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml',
205-
).create(recursive: true).then((File adaptiveIcon) {
206-
adaptiveIcon.writeAsString(xml_template.icLauncherDrawableBackgroundXml);
207-
});
208-
} else {
209-
File(
210-
constants.androidAdaptiveXmlFolder(flavor) +
211-
constants.androidDefaultIconName +
212-
'.xml',
213-
).create(recursive: true).then((File adaptiveIcon) {
214-
adaptiveIcon.writeAsString(xml_template.icLauncherDrawableBackgroundXml);
215-
});
216-
}
217258
}
218259

219260
/// Creates a colors.xml file if it was missing from android/app/src/main/res/values/colors.xml

lib/config/config.dart

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ class Config {
2525
this.ios = false,
2626
this.imagePathAndroid,
2727
this.imagePathIOS,
28+
this.imagePathIOSDarkTransparent,
29+
this.imagePathIOSTintedGrayscale,
2830
this.adaptiveIconForeground,
31+
this.adaptiveIconForegroundInset = 16,
2932
this.adaptiveIconBackground,
33+
this.adaptiveIconMonochrome,
3034
this.minSdkAndroid = constants.androidDefaultAndroidMinSDK,
3135
this.removeAlphaIOS = false,
36+
this.desaturateTintedToGrayscaleIOS = false,
3237
this.backgroundColorIOS = '#ffffff',
3338
this.webConfig,
3439
this.windowsConfig,
@@ -116,14 +121,30 @@ class Config {
116121
@JsonKey(name: 'image_path_ios')
117122
final String? imagePathIOS;
118123

119-
/// android adaptive icon foreground image
124+
/// IOS image_path_ios_dark_transparent
125+
@JsonKey(name: 'image_path_ios_dark_transparent')
126+
final String? imagePathIOSDarkTransparent;
127+
128+
/// IOS image_path_ios_tinted_grayscale
129+
@JsonKey(name: 'image_path_ios_tinted_grayscale')
130+
final String? imagePathIOSTintedGrayscale;
131+
132+
/// android adaptive_icon_foreground image
120133
@JsonKey(name: 'adaptive_icon_foreground')
121134
final String? adaptiveIconForeground;
122135

136+
/// android adaptive_icon_foreground inset
137+
@JsonKey(name: 'adaptive_icon_foreground_inset')
138+
final int adaptiveIconForegroundInset;
139+
123140
/// android adaptive_icon_background image
124141
@JsonKey(name: 'adaptive_icon_background')
125142
final String? adaptiveIconBackground;
126143

144+
/// android adaptive_icon_background image
145+
@JsonKey(name: 'adaptive_icon_monochrome')
146+
final String? adaptiveIconMonochrome;
147+
127148
/// Android min_sdk_android
128149
@JsonKey(name: 'min_sdk_android')
129150
final int minSdkAndroid;
@@ -132,6 +153,10 @@ class Config {
132153
@JsonKey(name: 'remove_alpha_ios')
133154
final bool removeAlphaIOS;
134155

156+
/// IOS desaturate_tinted_to_grayscale
157+
@JsonKey(name: 'desaturate_tinted_to_grayscale_ios')
158+
final bool desaturateTintedToGrayscaleIOS;
159+
135160
/// IOS background_color_ios
136161
@JsonKey(name: 'background_color_ios')
137162
final String backgroundColorIOS;
@@ -157,6 +182,11 @@ class Config {
157182
adaptiveIconForeground != null &&
158183
adaptiveIconBackground != null;
159184

185+
/// whether or not there is configuration for monochrome icons for android
186+
bool get hasAndroidAdaptiveMonochromeConfig {
187+
return isNeedingNewAndroidIcon && adaptiveIconMonochrome != null;
188+
}
189+
160190
/// Checks if contains any platform config
161191
bool get hasPlatformConfig {
162192
return ios != false ||

0 commit comments

Comments
 (0)