简体   繁体   English

如何在 Flutter 中更改状态栏和应用栏颜色?

[英]How to change Status Bar and App Bar color in Flutter?

I'm trying to change the color of the system status bar to black.我正在尝试将系统状态栏的颜色更改为黑色。 The configuration seems to be overridden by the AppBar class. I can achieve what I want by assigning the theme: to ThemeData.dark() when creating the Material App, and then specifying an appBar attribute .该配置似乎被 AppBar class 覆盖。我可以通过分配主题来实现我想要的:在创建 Material App 时分配给ThemeData.dark() ,然后指定appBar attribute But I don't want an AppBar, and also, doing it this way changes all the font colors.但我不想要 AppBar,而且,这样做会更改所有字体 colors。

A possible solution is to inherit ThemeData.bright() into a new class, then add something that only changes the system status bar through一个可能的解决方案是继承ThemeData.bright() 成一个新的class,然后通过添加一些只改变系统状态栏的东西

setSystemUIOverlayStyle

And then I would need to specify AppBar and make it invisible somehow?然后我需要指定 AppBar 并以某种方式使其不可见?

Documentation 文档

main.dart主要.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:english_words/english_words.dart';
import 'layout_widgets.dart' as layout_widgets;

class RandomWords extends StatefulWidget {
  @override
  createState() => new RandomWordsState();
}
class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _saved = new Set<WordPair>();
  final _biggerFont = const TextStyle(fontSize: 18.0);

  void _pushSaved() {
     Navigator.of(context).push(
       new MaterialPageRoute(
           builder: (context) {
             final tiles = _saved.map((pair) {
               return new ListTile(
                 title: new Text(pair.asPascalCase,style:_biggerFont)
               );
              }
             );
             final divided = ListTile.divideTiles(
               context:context,
                 tiles: tiles,).toList();
             return new Scaffold(
               appBar: new AppBar(
                 title: new Text('Saved Suggestions'),
               ),
               body: new ListView(children:divided),
             );
           }
       )
     );
  }

  Widget _buildSuggestions() {
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      // The item builder callback is called once per suggested word pairing,
      // and places each suggestion into a ListTile row.
      // For even rows, the function adds a ListTile row for the word pairing.
      // For odd rows, the function adds a Divider widget to visually
      // separate the entries. Note that the divider may be difficult
      // to see on smaller devices.
      itemBuilder: (context, i) {
        // Add a one-pixel-high divider widget before each row in theListView.
        if (i.isOdd) return new Divider();
        // The syntax "i ~/ 2" divides i by 2 and returns an integer result.
        // For example: 1, 2, 3, 4, 5 becomes 0, 1, 1, 2, 2.
        // This calculates the actual number of word pairings in the ListView,
        // minus the divider widgets.
        final index = i ~/ 2;
        // If you've reached the end of the available word pairings...
        if (index >= _suggestions.length) {
          // ...then generate 10 more and add them to the suggestions list.
          _suggestions.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_suggestions[index]);
      }
    );
  }

  Widget _buildRow(WordPair pair) {
    final alreadySaved = _saved.contains(pair);
    return new ListTile(
      title: new Text(
          pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Startup Name Generator'),
        actions: <Widget>[
          new IconButton(icon:new Icon(Icons.list), onPressed: _pushSaved),
        ],
      ),
      body: _buildSuggestions(),
    );
  }

}


void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Column buildButtonColumn(IconData icon, String label) {
      Color color = Theme.of(context).primaryColor;
      return new Column(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new Icon(icon, color: color),
          new Container(
            margin: const EdgeInsets.only(top:8.0),
            child: new Text(
              label,
              style: new TextStyle(
                fontSize: 12.0,
                fontWeight: FontWeight.w400,
                color: color,
              )
            ),
          )
        ],

      );
    }
    Widget titleSection = layout_widgets.titleSection;
    Widget buttonSection = new Container(
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          buildButtonColumn(Icons.contact_mail, "CONTACT"),
          buildButtonColumn(Icons.folder_special, "PORTFOLIO"),
          buildButtonColumn(Icons.picture_as_pdf, "BROCHURE"),
          buildButtonColumn(Icons.share, "SHARE"),
        ],
      )
    );
    Widget textSection = new Container(
      padding: const EdgeInsets.all(32.0),
      child: new Text(
        '''
The most awesome apps done here.
        ''',
        softWrap: true,
      ),
    );
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
    return new MaterialApp(
      title: 'Startup Name Generator',
//      theme: new ThemeData(
//          brightness: Brightness.dark,
//          primarySwatch: Colors.blue,
//      ),
//      theme: new ThemeData(),
      debugShowCheckedModeBanner: false,

      home: new Scaffold(
//        appBar: new AppBar(
////          title: new Text('Top Lakes'),
////          brightness: Brightness.light,
//        ),
//        backgroundColor: Colors.white,
        body: new ListView(
          children: [
            new Padding(
              padding: new EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 0.0),
              child: new Image.asset(
                  'images/lacoder-logo.png',
                  width: 600.0,
                  height: 240.0,
                  fit: BoxFit.fitHeight,

              ),
            ),

            titleSection,
            buttonSection,
            textSection,
          ],
        ),
      ),
    );
  }
}

layout_widgets.dart layout_widgets.dart

import 'package:flutter/material.dart';

Widget titleSection = new Container(
    padding: const EdgeInsets.all(32.0),
    child: new Row(children: [
      new Expanded(
          child: new Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          new Container(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: new Text(
                "Some-Website.com",
                style: new TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              )
          ),
          new Text(
            'Small details',
            style: new TextStyle(
              color: Colors.grey[500],
            )
          )
        ],
      )),
      new Icon(Icons.star,color: Colors.orange[700]),
      new Text('100'),
    ]));

I tried the method SystemChrome.setSystemUIOverlayStyle() , as far as I tested (Flutter SDK v1.9.1+hotfix.2, running on iOS 12.1) it works perfect for Android.我尝试了SystemChrome.setSystemUIOverlayStyle()方法,据我测试(Flutter SDK v1.9.1+hotfix.2,在 iOS 12.1 上运行)它非常适合 Android。 But for iOS, eg if your first screen FirstScreen() doesn't have an AppBar , but the second SecondScreen() does, then at launch the method does set the color in FirstScreen() .但是对于iOS,例如,如果您的第一个屏幕FirstScreen()没有AppBar ,但第二个SecondScreen()有,那么在启动时该方法确实在FirstScreen()中设置颜色。 However, after navigating back to FirstScreen() from SecondScreen() , the status bar color becomes transparent.然而,导航回到后FirstScreen()SecondScreen()状态栏颜色变成透明。

I come up with a hacky workaround by setting an AppBar() with zero height, then status bar's color gets changed by the AppBar, but the AppBar itself is not visible.我通过设置一个高度为零的AppBar()提出了一个hacky 解决方法,然后状态栏的颜色被 AppBar 改变,但 AppBar 本身不可见。 Hope it would be useful to someone.希望它对某人有用。

// FirstScreen that doesn't need an AppBar
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: PreferredSize(
        preferredSize: Size.fromHeight(0),
        child: AppBar( // Here we create one to set status bar color
          backgroundColor: Colors.black, // Set any color of status bar you want; or it defaults to your theme's primary color
        )
      )
  );
}

// SecondScreen that does have an AppBar
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar()
  }
}

Here is the screenshot of FirstScreen in iPhone Xs Max iOS 12.1:这是 iPhone Xs Max iOS 12.1 中FirstScreen的屏幕截图:

在此处输入图片说明

Both iOS and Android: iOS 和安卓系统:

appBar: AppBar(
  backgroundColor: Colors.red, // status bar and navigation bar color
  brightness: Brightness.light, // status bar brightness
)

Only for Android (More flexibility)仅适用于 Android(更灵活)

You can use SystemChrome class to change Status bar and Navigation bar color.您可以使用SystemChrome类来更改状态栏和导航栏的颜色。 First import第一次导入

import 'package:flutter/services.dart';

After this, you need to add following lines (better place to put these lines is in your main() method)在此之后,您需要添加以下几行(放置这些行的更好位置是在您的main()方法中)

void main() {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    systemNavigationBarColor: Colors.blue,
    statusBarColor: Colors.pink,
  ));
}

If you don't want AppBar at all, then you can just call setSystemUIOverlayStyle in the main function:如果你根本不需要 AppBar,那么你可以在主函数中调用setSystemUIOverlayStyle

void main() async {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);

  runApp(new MaterialApp(
    home: new Scaffold(),
  ));
}

It's more tricky if you have an app bar in one scaffold, and none in another.如果您在一个脚手架中有一个应用程序栏,而在另一个脚手架中没有,那就更棘手了。 In that case I had to call setSystemUIOverlayStyle after pushing new route with a scaffold that does not have an appbar:在这种情况下,我不得不在使用没有应用setSystemUIOverlayStyle的脚手架推送新路由后调用setSystemUIOverlayStyle

@override
Widget build(BuildContext context) {
  final page = ModalRoute.of(context);
  page.didPush().then((x) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
  });

  return new Scaffold();
}

I'm quite new to StackOverflow & I've never used Flutter however I have found this package that seems to make things relatively easy.我对 StackOverflow 很陌生,我从未使用过 Flutter,但是我发现这个包似乎让事情变得相对简单。

Method 1: Using the package方法一:使用包

Once this is imported all you need to do is add this code fragment:导入后,您只需添加以下代码片段:

try {
await FlutterStatusbarcolor.setStatusBarColor(Colors.black);
} on PlatformException catch (e) {
print(e);
}

Replacing the parameter for the setStatusBarColor() should give you the desired result, a full list of colours can be found here .替换setStatusBarColor()的参数应该会给您所需的结果,可以在此处找到完整的颜色列表。

Method 2: Using default functions方法二:使用默认函数

If this doesn't work / you don't want to add extra packages or libraries then perhaps this StackOverflow answer may help.如果这不起作用/您不想添加额外的包或库,那么这个StackOverflow 答案可能会有所帮助。

It involves using a similar function to the above method: getWindow().setStatusBarColor() or getActivity().getWindow().setStatusBarColor()它涉及使用与上述方法类似的函数: getWindow().setStatusBarColor()getActivity().getWindow().setStatusBarColor()

Replacing the parameter with the desired hex code from the same list as earlier may also result in a solution.之前相同列表中的所需十六进制代码替换参数也可能会产生解决方案。

Hope it works/helps!希望它有效/有帮助!

i have achieved that way我已经做到了

  @override
void initState() {
  super.initState();
  // Transparent status bar
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(statusBarColor: Colors.transparent,));
}

you can also see different properties after comma您还可以在逗号后看到不同的属性

SystemUiOverlayStyle(statusBarColor: Colors.transparent,)

just use combination of ctrl + space after comma and you will get what you can use.只需在逗号后使用 ctrl + space 的组合,您就会得到您可以使用的内容。

在此处输入图片说明

Please read this flutter package .请阅读这个颤振包 To set status bar text as black, you can set FlutterStatusbarcolor.setStatusBarWhiteForeground(false) .要将状态栏文本设置为黑色,您可以设置FlutterStatusbarcolor.setStatusBarWhiteForeground(false) you need to have this line of code in didChangeAppLifecycleState method with resume state so that when you go to other application and come back, the status bar text color are set to your initial setup.您需要在didChangeAppLifecycleState方法中使用恢复状态的这行代码,以便当您转到其他应用程序并返回时,状态栏文本颜色设置为您的初始设置。

Also, you need to set the your AppBar's TextTheme.此外,您需要设置您的 AppBar 的 TextTheme。 like following.喜欢以下。

Widget build(BuildContext context) {
FlutterStatusbarcolor.setStatusBarWhiteForeground(false);
return MaterialApp(
    title:// title goes here
    theme:// your theme goes here
    home:   Scaffold(
      appBar: AppBar(
                      backgroundColor: Colors.white,
                      title: _loadAppBarTitle(),
                      textTheme: Theme.of(context).textTheme),
      body: //body's goes here
  );
);

Hopefully, this one can help somebody who has the similar problem with me.希望这个可以帮助和我有类似问题的人。

Flutter 2.5.1 Flutter 2.5.1

'brightness' is deprecated and shouldn't be used. This property is no longer used, please use systemOverlayStyle instead. This feature was deprecated after v2.4.0-0.0.pre.. Try replacing the use of the deprecated member with the replacement.

Old code旧代码

brightness: Brightness.dark,

New code新密码

systemOverlayStyle: SystemUiOverlayStyle(
 systemNavigationBarColor: Colors.blue, // Navigation bar
 statusBarColor: Colors.red, // Status bar
),

Just write this code inside the AppBar只需在 AppBar 中编写此代码

Scaffold(
          drawer: const SideBar(),
          appBar: AppBar(
            title: const Text("SomeThing"),
            systemOverlayStyle: SystemUiOverlayStyle.dark,//this is what you wanted
          ),
          body: YourWidget()

TLDR; TLDR; you need to use Scaffold , it manages the colors even if you navigate back and forth.您需要使用Scaffold ,即使您来回导航,它也会管理颜色。

Scaffold(
    appBar: AppBar(brightness: Brightness.dark), \\ dark content -> white app bar
    body: ...
);

If your screen does not have an app bar, then you need to use AnnotatedRegion with scaffold in order to achieve the same effect.如果您的屏幕没有应用栏,那么您需要将AnnotatedRegion脚手架一起使用才能达到相同的效果。

AnnotatedRegion(
    value: SystemUiOverlayStyle.light, // this will make the app bar white
    child: Scaffold(
          body: 
    ),
);

Instead of SystemUiOverlayStyle.light , you can customize it:您可以自定义它而不是SystemUiOverlayStyle.light

SystemUiOverlayStyle(
  statusBarBrightness: Brightness.light, 
  systemNavigationBarDividerColor: Colors.blue,
  ...
);

For some reason, it didn't work for me when I put my AppBar directly in my Scaffold, so I added it like this:出于某种原因,当我将我的 AppBar 直接放在我的脚手架中时它对我不起作用,所以我这样添加它:

Scaffold(
  extendBodyBehindAppBar: true,
  body: Stack (
    children: [
      AppBar(
        automaticallyImplyLeading: false,
        backgroundColor: Colors.transparent,
        systemOverlayStyle: SystemUiOverlayStyle.light,
      ),
      // ... other widgets
    ],
  ),
)

And it changed the color of both my status bar and navigation bar (background of home indicator in Android)它改变了我的状态栏和导航栏的颜色(Android 中主页指示器的背景)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM