Last active
July 3, 2023 19:15
-
-
Save arxdeus/cebbcfef0b49c3baf0ba16f3038f3239 to your computer and use it in GitHub Desktop.
Animate system chrome (StatusBar & NavBar) during animating between routes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'system_chrome_animation.dart'; | |
class AnimatedMaterialRoute<T> extends MaterialPageRoute<T> with SystemChromeAnimationMixin { | |
AnimatedMaterialRoute({required super.builder, required this.originColor, required this.targetColor}); | |
@override | |
final Color originColor; | |
@override | |
final Color targetColor; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/services.dart'; | |
import 'package:meta/meta.dart'; | |
/// Use this mixin to animate navigation bar color (android only). | |
/// When you are using annotated region or SystemChrome.setUiOverlayStyle color | |
/// will be set with delay and without animation. With current implementation | |
/// navbar color will be interpolated between [originColor] and [targetColor] colors. | |
mixin SystemChromeAnimationMixin<T> on ModalRoute<T> { | |
@mustBeOverridden | |
Color get originColor; | |
@mustBeOverridden | |
Color get targetColor; | |
@override | |
Widget buildPage( | |
BuildContext context, | |
Animation<double> animation, | |
Animation<double> secondaryAnimation, | |
) { | |
///take overlays control from AnnotatedRegions widgets | |
WidgetsBinding.instance.renderView.automaticSystemUiAdjustment = false; | |
///Listen to route animation and applying colors linear interpolation. | |
animation.addListener(() { | |
unawaited(setNavBar(context, animation.value)); | |
}); | |
return super.buildPage(context, animation, secondaryAnimation); | |
} | |
/// Copy of _toMap implementation from SystemChrome class. | |
Map<String, dynamic> _toMap(SystemUiOverlayStyle style) { | |
return <String, dynamic>{ | |
'systemNavigationBarColor': style.systemNavigationBarColor?.value, | |
'systemNavigationBarDividerColor': style.systemNavigationBarDividerColor?.value, | |
'systemStatusBarContrastEnforced': style.systemStatusBarContrastEnforced, | |
'statusBarColor': style.statusBarColor?.value, | |
'statusBarBrightness': style.statusBarBrightness?.toString(), | |
'statusBarIconBrightness': style.statusBarIconBrightness?.toString(), | |
'systemNavigationBarIconBrightness': style.systemNavigationBarIconBrightness?.toString(), | |
'systemNavigationBarContrastEnforced': style.systemNavigationBarContrastEnforced, | |
}; | |
} | |
Future<void> setNavBar(BuildContext context, double value) async { | |
if (context.mounted) { | |
final color = Color.lerp( | |
originColor, | |
targetColor, | |
value, | |
); | |
/// Same implementation as in SystemChrome.setUiOverlayStyle, but without | |
/// microtask scheduling | |
await SystemChannels.platform.invokeMethod<void>( | |
'SystemChrome.setSystemUIOverlayStyle', | |
_toMap( | |
// ignore: invalid_use_of_visible_for_testing_member | |
SystemChrome.latestStyle!.copyWith( | |
systemNavigationBarIconBrightness: Theme.of(context).brightness, | |
// uncomment this if you want to change | |
// color of status bar too | |
// | |
// statusBarColor: color, | |
systemNavigationBarColor: color, | |
), | |
), | |
); | |
} | |
} | |
@override | |
bool didPop(T? result) { | |
/// switching ui adjustment after pop for returning overlays control to | |
/// AnnotatedRegion. | |
WidgetsBinding.instance.renderView.automaticSystemUiAdjustment = true; | |
animation?.removeListener(() {}); | |
return super.didPop(result); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
inspired by https://gist.github.com/mikitakalinovsky/f1c2c5dc86ef960b564f67116f60dd49