美文网首页
在flutter更改单个页面导航栏和状态栏的颜色,push页面或

在flutter更改单个页面导航栏和状态栏的颜色,push页面或

作者: 大宝来巡山 | 来源:发表于2024-04-25 18:02 被阅读0次

    最近更换播放器需求,需要对播放器页面单独设置状态栏和导航栏,而在其他页面恢复之前系统设置的颜色:
    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;
    
    }
    

    相关文章

      网友评论

          本文标题:在flutter更改单个页面导航栏和状态栏的颜色,push页面或

          本文链接:https://www.haomeiwen.com/subject/uxpnxjtx.html