From e9e0e4f5d324b5b26ed4a245447e6deed612f355 Mon Sep 17 00:00:00 2001 From: Xavier Hainaux Date: Thu, 11 Nov 2021 19:47:23 +0100 Subject: [PATCH] Add examples for a splash screen --- example/ios/Flutter/AppFrameworkInfo.plist | 2 +- example/ios/Podfile | 76 ++++------------ example/ios/Podfile.lock | 14 +-- example/ios/Runner.xcodeproj/project.pbxproj | 11 +-- .../contents.xcworkspacedata | 2 +- example/lib/examples/splash_screen.dart | 56 ++++++++++++ example/lib/examples/splash_screen_alt.dart | 86 +++++++++++++++++++ example/pubspec.lock | 49 +++++------ 8 files changed, 187 insertions(+), 109 deletions(-) create mode 100644 example/lib/examples/splash_screen.dart create mode 100644 example/lib/examples/splash_screen_alt.dart diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 6b4c0f78..f2872cf4 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 6697f0a5..1e8c3c90 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -10,78 +10,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - generated_key_values = {} - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) do |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - generated_key_values[podname] = podpath - else - puts "Invalid plugin specification: #{line}" - end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches end - generated_key_values + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" end +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + target 'Runner' do use_frameworks! use_modular_headers! - # Flutter Pod - - copied_flutter_dir = File.join(__dir__, 'Flutter') - copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') - copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') - unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) - # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. - # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. - # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. - - generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') - unless File.exist?(generated_xcode_build_settings_path) - raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) - cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; - - unless File.exist?(copied_framework_path) - FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) - end - unless File.exist?(copied_podspec_path) - FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) - end - end - - # Keep pod path relative so it can be checked into Podfile.lock. - pod 'Flutter', :path => 'Flutter' - - # Plugin Pods - - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.each do |name, path| - symlink = File.join('.symlinks', 'plugins', name) - File.symlink(path, symlink) - pod name, :path => File.join(symlink, 'ios') - end + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end post_install do |installer| installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end + flutter_additional_ios_build_settings(target) end end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a43cd986..0ac05ae6 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2,27 +2,21 @@ PODS: - Flutter (1.0.0) - path_provider (0.0.1): - Flutter - - path_provider_macos (0.0.1): - - Flutter DEPENDENCIES: - Flutter (from `Flutter`) - path_provider (from `.symlinks/plugins/path_provider/ios`) - - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`) EXTERNAL SOURCES: Flutter: :path: Flutter path_provider: :path: ".symlinks/plugins/path_provider/ios" - path_provider_macos: - :path: ".symlinks/plugins/path_provider_macos/ios" SPEC CHECKSUMS: - Flutter: 0e3d915762c693b495b44d77113d4970485de6ec - path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d - path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0 + Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c -PODFILE CHECKSUM: c34e2287a9ccaa606aeceab922830efb9a6ff69a +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c -COCOAPODS: 1.9.1 +COCOAPODS: 1.11.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index b5b34b79..5fd5435a 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -264,12 +264,10 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../Flutter/Flutter.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -313,7 +311,6 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -353,7 +350,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -391,7 +388,6 @@ }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -437,7 +433,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -447,7 +443,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -487,7 +482,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a16..919434a6 100644 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/example/lib/examples/splash_screen.dart b/example/lib/examples/splash_screen.dart new file mode 100644 index 00000000..fe430e0a --- /dev/null +++ b/example/lib/examples/splash_screen.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; +import 'package:lottie/lottie.dart'; + +// This example show how to use a Lottie animation as a SplashScreen for your application +// Since animation are loaded from the assets and can take a few milliseconds to +// load, we instruct flutter to defer the first frame until when the animation +// is actually ready to be displayed. +void main() async { + Logger.root + ..level = Level.ALL + ..onRecord.listen(print); + + runApp(const SplashScreen()); +} + +class SplashScreen extends StatefulWidget { + const SplashScreen({Key? key}) : super(key: key); + + @override + _SplashScreenState createState() => _SplashScreenState(); +} + +class _SplashScreenState extends State + with TickerProviderStateMixin { + @override + void initState() { + super.initState(); + WidgetsBinding.instance!.deferFirstFrame(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + color: Colors.lightBlue, + home: Scaffold( + backgroundColor: Colors.lightBlue, + appBar: AppBar( + title: const Text('Splash screen'), + ), + body: SingleChildScrollView( + child: Center( + child: Column( + children: [ + Lottie.asset('assets/AndroidWave.json', + onLoaded: (composition) { + WidgetsBinding.instance!.allowFirstFrame(); + }), + ], + ), + ), + ), + ), + ); + } +} diff --git a/example/lib/examples/splash_screen_alt.dart b/example/lib/examples/splash_screen_alt.dart new file mode 100644 index 00000000..a39d9f08 --- /dev/null +++ b/example/lib/examples/splash_screen_alt.dart @@ -0,0 +1,86 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:logging/logging.dart'; +import 'package:lottie/lottie.dart'; + +void main() async { + Logger.root + ..level = Level.ALL + ..onRecord.listen(print); + + runApp(const MaterialApp( + color: Colors.lightBlue, + home: App(), + )); +} + +class App extends StatefulWidget { + const App({Key? key}) : super(key: key); + + @override + _AppState createState() => _AppState(); +} + +class _AppState extends State with TickerProviderStateMixin { + late Future _lottieAnimation; + + @override + void initState() { + super.initState(); + + // Start loading the animation in background here + _lottieAnimation = _loadAnimation(); + } + + Future _loadAnimation() async { + var asset = await rootBundle.load('assets/AndroidWave.json'); + return asset.buffer.asUint8List(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.lightBlue, + appBar: AppBar( + title: const Text('Splash screen'), + ), + body: Center( + child: ElevatedButton( + onPressed: () async { + var bytes = await _lottieAnimation; + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AnimationScreen( + animationBytes: bytes, + ), + ), + ); + }, + child: const Text('Open splash'), + ), + ), + ); + } +} + +class AnimationScreen extends StatelessWidget { + final Uint8List animationBytes; + + const AnimationScreen({Key? key, required this.animationBytes}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Animation'), + ), + body: Center( + child: Lottie.memory(animationBytes), + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index f4d06487..962ca3c7 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,14 +7,14 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.1.2" + version: "3.1.6" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.8.1" boolean_selector: dependency: transitive description: @@ -35,7 +35,7 @@ packages: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" clock: dependency: transitive description: @@ -89,14 +89,14 @@ packages: name: flutter_colorpicker url: "https://pub.dartlang.org" source: hosted - version: "0.5.0" + version: "0.6.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" flutter_test: dependency: "direct dev" description: flutter @@ -108,14 +108,14 @@ packages: name: golden_toolkit url: "https://pub.dartlang.org" source: hosted - version: "0.9.0" + version: "0.11.0" http: dependency: "direct main" description: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.13.3" + version: "0.13.4" http_parser: dependency: transitive description: @@ -136,14 +136,14 @@ packages: name: logging url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.2" lottie: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.2.0" + version: "1.2.1" matcher: dependency: transitive description: @@ -157,7 +157,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" path: dependency: transitive description: @@ -171,21 +171,21 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.6" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.1" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" path_provider_platform_interface: dependency: transitive description: @@ -199,35 +199,28 @@ packages: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.1" + version: "2.0.4" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.2" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.2.1" + version: "4.2.4" sky_engine: dependency: transitive description: flutter @@ -274,7 +267,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.2" typed_data: dependency: transitive description: @@ -295,7 +288,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.2.5" + version: "2.2.10" xdg_directories: dependency: transitive description: @@ -304,5 +297,5 @@ packages: source: hosted version: "0.2.0" sdks: - dart: ">=2.13.0 <3.0.0" - flutter: ">=1.20.0" + dart: ">=2.14.0 <3.0.0" + flutter: ">=2.5.0"