最近更换播放器需求,需要对播放器页面单独设置状态栏和导航栏,而在其他页面恢复之前系统设置的颜色:
1.进入播放页面之前状态栏为(SystemUiOverlayStyle.dark)文字/icon为黑色,背景白色;
2.播放页面背景黑色,自定义状态栏/导航栏背景透明、文字icon为白色(SystemUiOverlayStyle.light);
3.播放器push的新页面或者播放器页面返回到其他页面,恢复之前系统设置的状态栏、导航栏颜色;
一、main.dart 对全局导航栏状态栏的设置
class MyApp extends App {
final CustomRouteObserver<PageRoute> routeObserver =
CustomRouteObserver<PageRoute>();
MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomGetMaterialApp(
enableLog: false,
darkTheme: appThemeData,
debugShowCheckedModeBanner: false,
onInit: () {
///-------默认设置状态栏文字icon为黑色-------
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
},
title: 'appXXX',
navigatorKey: appNavigatorKey,
theme: appThemeData,
color: primaryColor,
///-------默认为浅色模式,app不受系统暗黑模式影响-----
themeMode: ThemeMode.light,
builder: bundleBaseAppTransitionBuilder(
builder: (_, child) =>
TopBannerWidget(child: AppListenerWidget(child: child!))),
///-----路由监听------
navigatorObservers: [
BotToastNavigatorObserver(),
RouteObserverUtil().routeObserver,
routeObserver
],
initialRoute: PageAddress.MainPage,
onGenerateRoute: super.onGenerateRoute,
onUnknownRoute: super.onUnknownRoute,
unknownRoute: unknownRoute,
localizationsDelegates: super.localizationsDelegates([
AppLocalizationDelegate.delegate,
///必须:否则播放器页面会报错! 播放器UI国际化
if (FunctionRegistry.callMaybe('@SuperPlayerWidgetLocals') != null)
FunctionRegistry.callMaybe('@SuperPlayerWidgetLocals'),
GlobalWidgetsLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
]),
supportedLocales: const [
Locale.fromSubtags(languageCode: 'en'),
Locale.fromSubtags(languageCode: 'zh'),
],
locale: const Locale('zh', 'CN'),
getPages: super.initGetPages,
);
}
ThemeData appThemeData = ThemeData(
brightness: Brightness.light,
platform: TargetPlatform.iOS,
primarySwatch: primaryColor,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
/// 用于界面主色 按钮颜色、重要提示、按钮等
// primaryColor: const Color(0xFF65C5BC),//old
primaryColor: primaryColor,
/// 警示色用于文字图标icon等
errorColor: redColor,
/// 禁用按钮色
disabledColor: const Color(0x99D3D3E2),
/// 少量用于链接色
// accentColor: Color(0xFF2A7BFF),
/// 指示器颜色
indicatorColor: primaryColor,
/// 按钮水波纹
// splashColor: Colors.transparent,
/// 表单输入文字提示的颜色
hintColor: const Color(0xFFB7BBBF),
appBarTheme: defAppBarTheme,
textTheme: const TextTheme(
/// 大标题,粗体 24
headline5: TextStyle(
color: textBigTitleColor,
fontSize: 24,
// overflow: TextOverflow.ellipsis,
),
///标题,粗体 16
subtitle1: TextStyle(
color: textTitleColor,
fontSize: 16,
// overflow: TextOverflow.ellipsis,
),
/// 次要信息文字,粗体 14
subtitle2: TextStyle(
color: textTitleColor,
fontSize: 15,
// overflow: TextOverflow.ellipsis,
),
bodyText1: TextStyle(
color: textTitleColor,
fontSize: 13,
// overflow: TextOverflow.ellipsis,
),
bodyText2: TextStyle(
color: textHelpColor,
fontSize: 12,
// overflow: TextOverflow.ellipsis,
),
),
/// 文字类
inputDecorationTheme: const InputDecorationTheme(
hintStyle: TextStyle(
color: Color(0xFFB7BBBF), // 表单输入文字提示的颜色
),
),
/// 背景色
scaffoldBackgroundColor: Colors.white,
// scaffoldBackgroundColor: backgroundColor,
backgroundColor: Colors.white,
/// 分割线
dividerColor: dividerColor,
// tabBarTheme: TabBarTheme(
// unselectedLabelColor: Color(0xFF9F9FB2),
// ),
unselectedWidgetColor: const Color(0xFFB7BBBF),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
splashFactory: const NoSplashFactory(),
backgroundColor: Colors.transparent,
textStyle: const TextStyle(color: Colors.white, fontSize: 14),
)),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
primary: primaryColor,
splashFactory: const NoSplashFactory(),
textStyle: const TextStyle(color: Colors.white, fontSize: 16),
)),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
primary: primaryColor,
splashFactory: const NoSplashFactory(),
textStyle: const TextStyle(color: primaryColor, fontSize: 14),
)),
iconTheme: const IconThemeData(
color: iconGrayColor,
),
primaryIconTheme: const IconThemeData(
color: Colors.deepPurpleAccent,
),
dividerTheme: const DividerThemeData(
thickness: 0.5,
),
bottomSheetTheme: const BottomSheetThemeData(
backgroundColor: Colors.white,
),
buttonTheme: const ButtonThemeData(),
toggleableActiveColor: primaryColor[250],
checkboxTheme: const CheckboxThemeData(
shape: CircleBorder(),
side: BorderSide(width: 1.5, color: grayColor),
splashRadius: 0,
),
);
二、播放器页面对导航栏状态栏的修改设置
@override
Widget build(BuildContext context) {
super.build(context);
SystemUiOverlayStyle value;
if(Platform.isAndroid){
value = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,/// 安卓系统状态栏存在底色,所以需要加这个
systemNavigationBarColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.light,
statusBarIconBrightness: Brightness.light,/// 状态栏字体颜色
statusBarBrightness: Brightness.light,
);
}else{
///iOS设置状态栏的正确姿势
value = SystemUiOverlayStyle.light;
}
return WillPopScope(
onWillPop: () async {
///页面返回时,恢复全局设置的系统导航栏颜色
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
_backBtnActionOrPip();
return true;
},
///重点来了:单独对某个页面设置导航栏需要使用AnnotatedRegion这个小部件-----
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: value,
child: Scaffold(
///--------设置页面背景色黑色----------
backgroundColor: Colors.black,
body: SafeArea(
bottom: false,
child: Stack(
children: [
Column(
children: [
///三、导航:返回按钮、下载、分享
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(0, 0, 0, 0.2),
Color.fromRGBO(0, 0, 0, 0),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
child: AppBar(
///--------设置背景色透明----------
backgroundColor: Colors.transparent,
leading: BackButton(
color: Colors.white,
onPressed: _backBtnActionOrPip,
),
actions: [],
),
....
],
....
),
///页面返回时,恢复全局设置的系统导航栏颜色
@override
void dispose() {
super.dispose();
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
}
三、播放器push到其他 页面对导航栏状态栏的恢复设置
思路一:push的页面,对导航栏状态栏的重新设置
总结下来,iOS想设置恢复成原来的状态栏颜色,要设置2步 ;安卓可以不要设置,自动读取全局设置的系统状态栏颜色,请看代码:
@override
Widget build(BuildContext context) {
SystemUiOverlayStyle value;
///安卓不设置也会自动取全局系统设置的颜色
if(Platform.isAndroid){
value = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,/// 安卓系统状态栏存在底色,所以需要加这个
systemNavigationBarColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.dark,
statusBarIconBrightness: Brightness.dark,/// 状态栏字体颜色
statusBarBrightness: Brightness.dark,
);
}else{
///1.iOS恢复到黑色模式
value = SystemUiOverlayStyle.dark;
}
return Scaffold(
appBar: AppBar(
///2.对当个页面设置状态栏
systemOverlayStyle: value,
title: JUIText( '写笔记'),
actions: [
JUIButton.themeBackground(
onPressed: () {
///发布按钮点击事件
_publishButtonClick();
},
width: 55,
height: 28,
title: '发布',
fontSize: 14,
radius: 7,
isShowOnAppBar: true,
)
],
),
body: SafeArea(
...
)
)
这个是我对单个页面设置状态栏颜色的踩坑记录,如果老铁有好的解决思路,欢迎留言分享。
思路二:添加路由监听
///添加路由监听
class _LessonDetailPageState extends State<LessonDetailPage>
with RouteAware {
}
...
@override
void didChangeDependencies() {
RouteObserverUtil()
.routeObserver
.subscribe(this, ModalRoute.of(context) as ModalRoute); //订阅
super.didChangeDependencies();
}
@override
void didPush() {
super.didPush();
}
@override
void didPop() {
super.didPop();
}
@override
void didPopNext() {
super.didPopNext();
}
@override
void didPushNext() {
///这里延迟0.1秒执行,是为了确保已经push到其他页面了,当前页面路由已修改,再去修改导航栏状态栏,否则可能会被覆盖
Future.delayed(const Duration(milliseconds: 100)).then((value) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
});
super.didPushNext();
}
///页面释放,恢复之前系统的导航栏黑色设置
@override
void dispose() {
super.dispose();
RouteObserverUtil().routeObserver.unsubscribe(this);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
}
@override
Widget build(BuildContext context) {
super.build(context);
return WillPopScope(
onWillPop: () async {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
return true;
},
///状态栏小工具设置状态栏为白色
child: StatusBarChangeWidget(
isDark: false,
child: Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
...
)
)
)
}
封装了一个小工具类,需要的小伙伴可以直接拿去用:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class StatusBarChangeWidget extends StatelessWidget {
final Widget child;
final bool isDark;
const StatusBarChangeWidget({
Key? key,
required this.child,
this.isDark = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: getSystemUiOverlayStyle(isDark: isDark),
child: child,
);
}
}
///状态栏颜色设置,此方法抽出来了,全项目可以直接调用
getSystemUiOverlayStyle({bool isDark = true}) {
SystemUiOverlayStyle value;
if (Platform.isAndroid) {
value = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
/// 安卓系统状态栏存在底色,所以需要加这个
systemNavigationBarColor: Colors.transparent,
systemNavigationBarIconBrightness:
isDark ? Brightness.dark : Brightness.light,
statusBarIconBrightness: isDark ? Brightness.dark : Brightness.light,
/// 状态栏字体颜色
statusBarBrightness: isDark ? Brightness.dark : Brightness.light,
);
} else {
value = isDark ? SystemUiOverlayStyle.dark : SystemUiOverlayStyle.light;
}
return value;
}
RouteObserver工具类代码
import 'package:flutter/material.dart';
//RouteObserver工具类
class RouteObserverUtil{
static final _observerUtil = RouteObserverUtil._internal();
final RouteObserver<ModalRoute> _routeObserver = RouteObserver();
factory RouteObserverUtil(){
return _observerUtil;
}
RouteObserverUtil._internal();
RouteObserver<ModalRoute> get routeObserver => _routeObserver;
}