diff --git a/CHANGELOG.md b/CHANGELOG.md index d504848..6566391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## [2.1.0] - (2022-Mar-06) +* Expanded options for Android 12. Thanks [Jose](https://github.com/JCQuintas) for the [PR](https://github.com/jonbhanson/flutter_native_splash/pull/300) that served as a good starting point. ## [2.0.5] - (2022-Feb-20) * Converted to a plugin since there is now platform specific code. ## [2.0.4] - (2022-Feb-15) diff --git a/README.md b/README.md index e4f9194..4a19d56 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ First, add `flutter_native_splash` as a dependency in your pubspec.yaml file. ```yaml dependencies: - flutter_native_splash: ^2.0.5 + flutter_native_splash: ^2.1.0 ``` Don't forget to `flutter pub get`. @@ -53,21 +53,15 @@ flutter_native_splash: # png file and should be sized for 4x pixel density. #image: assets/splash.png - # This property allows you to specify an image used as branding in the splash screen. It must be - # a png file. Currently, it is only supported for Android and iOS. + # The branding property allows you to specify an image used as branding in the splash screen. + # It must be a png file. Currently, it is only supported for Android < v12 and iOS. #branding: assets/dart.png - # Specify your branding image for dark mode. - #branding_dark: assets/dart_dark.png - # To position the branding image at the bottom of the screen you can use bottom, bottomRight, # and bottomLeft. The default values is bottom if not specified or specified something else. - # - # Make sure this content mode value should not be similar to android_gravity value and - # ios_content_mode value. #branding_mode: bottom - # The color_dark, background_image_dark, and image_dark are parameters that set the background + # The color_dark, background_image_dark, image_dark, branding_dark are parameters that set the background # and image when the device is in dark mode. If they are not specified, the app will use the # parameters from above. If the image_dark parameter is specified, color_dark or # background_image_dark must be specified. color_dark and background_image_dark cannot both be @@ -75,6 +69,29 @@ flutter_native_splash: #color_dark: "#042a49" #background_image_dark: "assets/dark-background.png" #image_dark: assets/splash-invert.png + #branding_dark: assets/dart_dark.png + + # Android 12 handles the splash screen differently than previous versions. Please visit + # https://developer.android.com/guide/topics/ui/splash-screen + # Following are Android 12 specific parameter. + android_12: + # The image parameter sets the splash screen icon image. If this parameter is not specified, + # the app's launcher icon will be used instead. + # Please note that the splash screen will be clipped to a circle on the center of the screen. + # App icon with an icon background: This should be 960×960 pixels, and fit within a circle + # 640 pixels in diameter. + # App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle + # 768 pixels in diameter. + #image: assets/android12splash.png + + # App icon background color. + #icon_background_color: "#111111" + + # The image_dark parameter and icon_background_color_dark set the image and icon background + # color when the device is in dark mode. If they are not specified, the app will use the + # parameters from above. + #image_dark: assets/android12splash-invert.png + #icon_background_color_dark: "#eeeeee" # The android, ios and web parameters can be used to disable generating a splash screen on a given # platform. @@ -82,13 +99,6 @@ flutter_native_splash: #ios: false #web: false - # The mode to use for android 12 splash screen. The default behavior is to use the app's icon as - # the splash image, but we can customize that so we use the same asset that was provided to the - # image/image_dark parameter. - # Please note that the splash screen will be clipped to a circle on the center of the screen. - # More info https://developer.android.com/guide/topics/ui/splash-screen#splash_screen_dimensions - #android_12_mode: 'use_image' - # The position of the splash image can be set with android_gravity, ios_content_mode, and # web_image_mode parameters. All default to center. # @@ -165,9 +175,9 @@ If you find this package useful, you can support it for free by giving it a thum # Android 12 Support -Android 12 has a [new method](https://developer.android.com/about/versions/12/features/splash-screen) of adding splash screens, which consists of a window background, icon, and the icon background. This package supports setting the background color and gives you the options to use the launcher icon or use the provided splash image with the `android_12_mode` configuration option. +Android 12 has a [new method](https://developer.android.com/about/versions/12/features/splash-screen) of adding splash screens, which consists of a window background, icon, and the icon background. -The package will add a `styles.xml` in `values-v31` and `values-night-v31` resource folders, which will provide Android 12 support while maintaining the legacy splash screen for previous versions of Android. +The package provides Android 12 support while maintaining the legacy splash screen for previous versions of Android. ***PLEASE NOTE:*** The splash screen may not appear when you launch the app from Android Studio. However, it should appear when you launch by clicking on the launch icon in Android. diff --git a/example/pubspec.yaml b/example/pubspec.yaml index f01cd00..f61db21 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -111,21 +111,15 @@ flutter_native_splash: # png file and should be sized for 4x pixel density. image: assets/logo_lockup_flutter_vertical.png - # This property allows you to specify an image used as branding in the splash screen. It must be - # a png file. Currently, it is only supported for Android and iOS. + # The branding property allows you to specify an image used as branding in the splash screen. + # It must be a png file. Currently, it is only supported for Android < v12 and iOS. #branding: assets/dart.png - # Specify your branding image for dark mode. - #branding_dark: assets/dart_dark.png - # To position the branding image at the bottom of the screen you can use bottom, bottomRight, # and bottomLeft. The default values is bottom if not specified or specified something else. - # - # Make sure this content mode value should not be similar to android_gravity value and - # ios_content_mode value. #branding_mode: bottom - # The color_dark, background_image_dark, and image_dark are parameters that set the background + # The color_dark, background_image_dark, image_dark, branding_dark are parameters that set the background # and image when the device is in dark mode. If they are not specified, the app will use the # parameters from above. If the image_dark parameter is specified, color_dark or # background_image_dark must be specified. color_dark and background_image_dark cannot both be @@ -133,6 +127,28 @@ flutter_native_splash: color_dark: "#042a49" #background_image_dark: "assets/dark-background.png" image_dark: assets/logo_lockup_flutter_vertical_wht.png + #branding_dark: assets/dart_dark.png + + # Android 12 handles the splash screen differently than previous versions. Please visit + # https://developer.android.com/guide/topics/ui/splash-screen + # Following are Android 12 specific parameter. + android_12: + # The image parameter sets the splash screen icon image. If this parameter is not specified, + # the app's launcher icon will be used instead. + # App icon with an icon background: This should be 960×960 pixels, and fit within a circle + # 640 pixels in diameter. + # App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle + # 768 pixels in diameter. + #image: assets/android12splash.png + + # App icon background color. + #icon_background_color: "#eeeeee" + + # The image_dark parameter and icon_background_color_dark set the image and icon background + # color when the device is in dark mode. If they are not specified, the app will use the + # parameters from above. + #image_dark: assets/android12splash-invert.png + #icon_background_color_dark: "#111111" # The android, ios and web parameters can be used to disable generating a splash screen on a given # platform. diff --git a/lib/android.dart b/lib/android.dart index 3327010..2b84c19 100644 --- a/lib/android.dart +++ b/lib/android.dart @@ -37,16 +37,19 @@ final List<_AndroidDrawableTemplate> androidSplashImagesDark = void _createAndroidSplash({ required String? imagePath, required String? darkImagePath, - String? brandingImagePath, - String? brandingDarkImagePath, + required String? android12ImagePath, + required String? android12DarkImagePath, + required String? brandingImagePath, + required String? brandingDarkImagePath, required String? color, required String? darkColor, required String gravity, - String brandingGravity = 'bottom', + required String brandingGravity, required bool fullscreen, required String? backgroundImage, required String? darkBackgroundImage, - required String? android12Mode, + required String? android12IconBackgroundColor, + required String? darkAndroid12IconBackgroundColor, }) { if (imagePath != null) { _applyImageAndroid(imagePath: imagePath); @@ -67,6 +70,19 @@ void _createAndroidSplash({ ); } + //create android 12 image if provided. (otherwise uses launch icon) + if (android12ImagePath != null) { + _applyImageAndroid( + imagePath: android12ImagePath, fileName: 'android12splash.png'); + } + + if (android12DarkImagePath != null) { + _applyImageAndroid( + imagePath: android12DarkImagePath, + dark: true, + fileName: 'android12splash.png'); + } + _createBackground( colorString: color, darkColorString: darkColor, @@ -128,30 +144,36 @@ void _createAndroidSplash({ print('[Android] Updating styles...'); _applyStylesXml( - fullScreen: fullscreen, - file: _androidV31StylesFile, - template: _androidV31StylesXml, - android12BackgroundColor: color, - android12Mode: android12Mode); + fullScreen: fullscreen, + file: _androidV31StylesFile, + template: _androidV31StylesXml, + android12BackgroundColor: color, + android12ImagePath: android12ImagePath, + android12IconBackgroundColor: android12IconBackgroundColor, + ); if (darkColor != null) { _applyStylesXml( - fullScreen: fullscreen, - file: _androidV31StylesNightFile, - template: _androidV31StylesNightXml, - android12BackgroundColor: darkColor, - android12Mode: android12Mode); + fullScreen: fullscreen, + file: _androidV31StylesNightFile, + template: _androidV31StylesNightXml, + android12BackgroundColor: darkColor, + android12ImagePath: android12DarkImagePath, + android12IconBackgroundColor: darkAndroid12IconBackgroundColor, + ); } _applyStylesXml( - fullScreen: fullscreen, - file: _androidStylesFile, - template: _androidStylesXml); + fullScreen: fullscreen, + file: _androidStylesFile, + template: _androidStylesXml, + ); if (darkColor != null || darkBackgroundImage != null) { _applyStylesXml( - fullScreen: fullscreen, - file: _androidNightStylesFile, - template: _androidStylesNightXml); + fullScreen: fullscreen, + file: _androidNightStylesFile, + template: _androidStylesNightXml, + ); } } @@ -242,12 +264,14 @@ void _applyLaunchBackgroundXml( } /// Create or update styles.xml full screen mode setting -void _applyStylesXml( - {required bool fullScreen, - required String file, - required String template, - String? android12BackgroundColor, - String? android12Mode}) { +void _applyStylesXml({ + required bool fullScreen, + required String file, + required String template, + String? android12BackgroundColor, + String? android12ImagePath, + String? android12IconBackgroundColor, +}) { final stylesFile = File(file); print('[Android] - ' + file); if (!stylesFile.existsSync()) { @@ -258,18 +282,22 @@ void _applyStylesXml( } _updateStylesFile( - fullScreen: fullScreen, - stylesFile: stylesFile, - android12BackgroundColor: android12BackgroundColor, - android12Mode: android12Mode); + fullScreen: fullScreen, + stylesFile: stylesFile, + android12BackgroundColor: android12BackgroundColor, + android12ImagePath: android12ImagePath, + android12IconBackgroundColor: android12IconBackgroundColor, + ); } /// Updates styles.xml adding full screen property -Future _updateStylesFile( - {required bool fullScreen, - required File stylesFile, - required String? android12BackgroundColor, - required String? android12Mode}) async { +Future _updateStylesFile({ + required bool fullScreen, + required File stylesFile, + required String? android12BackgroundColor, + required String? android12ImagePath, + required String? android12IconBackgroundColor, +}) async { final stylesDocument = XmlDocument.parse(stylesFile.readAsStringSync()); final resources = stylesDocument.getElement('resources'); final styles = resources?.findElements('style'); @@ -310,11 +338,18 @@ Future _updateStylesFile( value: '#' + android12BackgroundColor); } - if (android12Mode == 'use_image') { + if (android12ImagePath != null) { replaceElement( launchTheme: launchTheme, name: 'android:windowSplashScreenAnimatedIcon', - value: '@drawable/splash'); + value: '@drawable/android12splash'); + } + + if (android12IconBackgroundColor != null) { + replaceElement( + launchTheme: launchTheme, + name: 'android:windowSplashScreenIconBackgroundColor', + value: '#' + android12IconBackgroundColor); } stylesFile.writeAsStringSync( diff --git a/lib/cli_commands.dart b/lib/cli_commands.dart index 9622899..dc55944 100644 --- a/lib/cli_commands.dart +++ b/lib/cli_commands.dart @@ -25,28 +25,41 @@ void createSplash({String? path}) { /// Create splash screens for Android and iOS based on a config argument void createSplashByConfig(Map config) { - var image = _checkImageExists(config: config, parameter: 'image'); - var darkImage = _checkImageExists(config: config, parameter: 'image_dark'); - var brandingImage = _checkImageExists(config: config, parameter: 'branding'); - var brandingDarkImage = + final String? image = _checkImageExists(config: config, parameter: 'image'); + final String? darkImage = + _checkImageExists(config: config, parameter: 'image_dark'); + final String? brandingImage = + _checkImageExists(config: config, parameter: 'branding'); + final String? brandingDarkImage = _checkImageExists(config: config, parameter: 'branding_dark'); - var color = parseColor(config['color']); - var darkColor = parseColor(config['color_dark']); - var backgroundImage = + final String? color = parseColor(config['color']); + final String? darkColor = parseColor(config['color_dark']); + final String? backgroundImage = _checkImageExists(config: config, parameter: 'background_image'); - var darkBackgroundImage = + final String? darkBackgroundImage = _checkImageExists(config: config, parameter: 'background_image_dark'); - var plistFiles = config['info_plist_files']; - var gravity = (config['fill'] ?? false) ? 'fill' : 'center'; + final plistFiles = config['info_plist_files']; + String gravity = (config['fill'] ?? false) ? 'fill' : 'center'; if (config['android_gravity'] != null) gravity = config['android_gravity']; - - var brandingGravity = config['branding_mode'] ?? 'bottom'; - - bool fullscreen = config['fullscreen'] ?? false; - String iosContentMode = config['ios_content_mode'] ?? 'center'; + final brandingGravity = config['branding_mode'] ?? 'bottom'; + final bool fullscreen = config['fullscreen'] ?? false; + final String iosContentMode = config['ios_content_mode'] ?? 'center'; final webImageMode = (config['web_image_mode'] ?? 'center'); - - final android12Mode = (config['android_12_mode'] ?? 'use_app_icon'); + String? android12Image; + String? android12DarkImage; + String? android12IconBackgroundColor; + String? darkAndroid12IconBackgroundColor; + if (config['android_12'] != null) { + var android12Config = config['android_12']; + android12Image = + _checkImageExists(config: android12Config, parameter: 'image'); + android12DarkImage = + _checkImageExists(config: android12Config, parameter: 'image_dark'); + android12IconBackgroundColor = + parseColor(android12Config['icon_background_color']); + darkAndroid12IconBackgroundColor = + parseColor(android12Config['icon_background_color_dark']); + } if (!config.containsKey('android') || config['android']) { if (Directory('android').existsSync()) { @@ -55,6 +68,10 @@ void createSplashByConfig(Map config) { darkImagePath: darkImage, brandingImagePath: brandingImage, brandingDarkImagePath: brandingDarkImage, + android12ImagePath: android12Image, + android12DarkImagePath: android12DarkImage, + android12IconBackgroundColor: android12IconBackgroundColor, + darkAndroid12IconBackgroundColor: darkAndroid12IconBackgroundColor, backgroundImage: backgroundImage, darkBackgroundImage: darkBackgroundImage, color: color, @@ -62,7 +79,6 @@ void createSplashByConfig(Map config) { gravity: gravity, brandingGravity: brandingGravity, fullscreen: fullscreen, - android12Mode: android12Mode, ); } else { print('Android folder not found, skipping Android splash update...'); @@ -187,9 +203,12 @@ Map getConfig({String? configFile}) { } // yamlMap has the type YamlMap, which has several unwanted side effects - final config = {}; - for (MapEntry entry - in yamlMap['flutter_native_splash'].entries) { + return _yamlToMap(yamlMap['flutter_native_splash']); +} + +Map _yamlToMap(YamlMap yamlMap) { + Map map = {}; + for (MapEntry entry in yamlMap.entries) { if (entry.value is YamlList) { var list = []; for (var value in (entry.value as YamlList)) { @@ -197,12 +216,14 @@ Map getConfig({String? configFile}) { list.add(value); } } - config[entry.key] = list; + map[entry.key] = list; + } else if (entry.value is YamlMap) { + map[entry.key] = _yamlToMap(entry.value); } else { - config[entry.key] = entry.value; + map[entry.key] = entry.value; } } - return config; + return map; } void _checkConfig(Map config) { @@ -232,6 +253,26 @@ void _checkConfig(Map config) { 'does not contain a `color_dark` or a `background_image_dark`.'); exit(1); } + + if (config.containsKey('android_12') && config['android_12'] is Map) { + Map android12Config = config['android_12']; + if (android12Config.containsKey('image_dark') && + !config.containsKey('color_dark') && + !config.containsKey('background_image_dark')) { + print('Your `flutter_native_splash` section contains ' + '`android_12:image_dark` but does not contain a `color_dark` or a ' + '`background_image_dark`.'); + exit(1); + } + if (android12Config.containsKey('image_dark') && + !config.containsKey('color_dark') && + !config.containsKey('icon_background_color_dark')) { + print('Your `flutter_native_splash` section contains ' + '`android_12:icon_background_color_dark` but does not contain a ' + '`color_dark` or a `background_image_dark`.'); + exit(1); + } + } } @visibleForTesting diff --git a/pubspec.yaml b/pubspec.yaml index 9e5a342..a4c8ae2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_native_splash description: Customize Flutter's default white native splash screen with background color and splash image. Supports dark mode, full screen, and more. -version: 2.0.5 +version: 2.1.0 homepage: https://github.com/jonbhanson/flutter_native_splash environment: