#flutter
#flutter
Вопрос:
Я пытаюсь добавить SafeArea
виджет для приложения flutter с раскрашенными системными панелями, но почему-то они всегда становятся черными.
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: kSurfaceColor,
statusBarIconBrightness: Brightness.dark,
statusBarColor: Colors.red, // Note RED here
),
);
return SafeArea(
child: Scaffold(
backgroundColor: kWhiteColor,
appBar: _buildAppBar(context), // Title and Avatar are built here
body: _buildBody(), // This function just returns blank Container for now
floatingActionButton: _buildFAB(context),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
),
);
}
Если я оберну SafeArea
внутри свойства, для Container
которого color
установлено значение white, это сработает, но значки системной панели также станут белыми
Ответ №1:
Основываясь на ответе @david-carrilho, я создал этот простой виджет
import 'package:flutter/material.dart';
class ColoredSafeArea extends StatelessWidget {
final Widget child;
final Color color;
const ColoredSafeArea({Key key, @required this.child, this.color})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: color ?? Theme.of(context).colorScheme.primaryVariant,
child: SafeArea(
child: child,
),
);
}
}
Затем, где бы я ни использовал SafeArea
, я использую свой маленький виджет-оболочку ColoredSafeArea
.
class MyExampleView extends StatelessWidget {
const MyExampleView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ColoredSafeArea(
child: Center(
child: Text('Nice color bar'),
),
);
}
}
Причина, по которой это работает, заключается в том, что это создает контейнер за вашим содержимым с указанным цветом, а затем SafeArea
просто добавляет необходимое заполнение в зависимости от устройства.
Комментарии:
1. Спасибо. Цвет работает, но сейчас я не вижу системных значков. Как их отобразить?
2. У меня такой же вопрос, как и у Kakyo. Может ли кто-нибудь поделиться подсветкой на нем?
Ответ №2:
Я знаю, что это старый вопрос, но после прочтения документации я придумал более полное решение.
В моем ответе учитывается следующее:
- Не помещайте каркасы в безопасные области;
- [iOS] покрасьте свой каркас в правильный цвет;
- [Android] программно настраивает системные панели.
1. Правильное использование SafeArea
SafeArea
это виджет, который выполняет MediaQuery
добавление некоторого надлежащего заполнения в ваше приложение. Это должно происходить внутри body
вашего Scaffold
приложения. Что-то подобное приведет к коду, который позже не будет неожиданно прерываться:
return Scaffold(
// ...
body: SafeArea( // your SafeArea should stay here
child: YourWidget(),
),
);
2. Заметка для iOS
Как уже говорилось в других ответах, вам просто нужно покрасить свой каркас так, чтобы вы получили нужный цвет. Ваш каркас должен включать backgroundColor
свойство (и панель приложений тоже, если она у вас есть).
return Scaffold(
// ...
backgroundColor: yourColor, // the RED you need
appBar: AppBar( // if any
backgroundColor: yourColor, // maybe RED here, also
// a system overlay option is included here, too, see 3.
// ...
),
body: SafeArea( // your SafeArea should stay here
child: YourWidget(),
),
);
3. Системный интерфейс Android
Как и в OP, вам нужно SystemChrome.setSystemUIOverlayStyle()
обратиться к системным цветам панели, связанным с Android.
Однако, в документации говорится, что этот метод следует вызывать программно всякий раз, когда открывается новая страница / новый маршрут, если у вас разные Route
цвета.
Предположим, у вас есть версия 2.0 Router
; затем вы должны написать ее build
метод следующим образом:
Widget build(BuildContext context) {
Color overlayColor = ... your color ...;
final systemBarColors = SystemUiOverlayStyle(
systemNavigationBarColor: overlayColor,
statusBarColor: overlayColor,
);
SystemChrome.setSystemUIOverlayStyle(systemBarColors);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: systemBarColors,
child: Navigator(
key: navigatorKey,
pages: _stack,
onPopPage: _onPopPage,
),
);
}
Это гарантирует, что каждый раз, когда открывается новая страница, т.е. вызывается build
наш Router
метод, системная панель Android и строка состояния отображаются должным образом.
Ответ №3:
Container(
color ...
),
child: SafeArea(
child: Scaffold(
body:
AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: ...
Комментарии:
1. Добро пожаловать в stackoverflow. В дополнение к предоставленному вами ответу, пожалуйста, рассмотрите возможность предоставления краткого объяснения того, почему и как это устраняет проблему.
2. Я отклонил это. Не используйте это решение,
SafeArea
они всегда должны находиться внутри каркаса. Это приводит к тому, что навигационные и системные панели становятся черными без причины.
Ответ №4:
В вашем случае просто перенос SafeArea()
на верхний виджет, который будет отображаться на экране (пример: ваш текстовый виджет «Сегодня»), должен избегать черного цвета на системной панели.
Полный пример.
Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SafeArea(
child: Text('Today'),
),
Text('Tomorrow')
]
);
У меня это сработало!
Ответ №5:
Замените свой стиль наложения приведенным ниже кодом, и он будет работать
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.dark.copyWith(statusBarColor: Colors.white));
Ответ №6:
установить только основной класс
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
statusBarIconBrightness: Brightness.light,
statusBarColor: HexColor(HexColor.primarycolor), // Note RED here
),
);
мой пример кода
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'HexColor.dart';
class CityListActiviy extends StatefulWidget {
// Initially password is obscure
@override
State<CityListActiviy> createState() => _CityListActiviyState();
}
class _CityListActiviyState extends State<CityListActiviy> {
TextEditingController userid_Controller = new TextEditingController();
bool userid_validate = false;
final String requiredNumber = '123456';
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
statusBarIconBrightness: Brightness.light,
statusBarColor: HexColor(HexColor.primarycolor), // Note RED here
),
);
return MaterialApp(
debugShowCheckedModeBanner: true,
home: LoaderOverlay(
child:SafeArea(
child: Scaffold(
backgroundColor: HexColor(HexColor.gray_activity_background),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Stack(
children: [
Container(
height: 60,
padding: new EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: HexColor(HexColor.white),
),
width: MediaQuery.of(context).size.width,
child: Text("Select Your Location",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.grey,
fontFamily: 'montserrat_medium',
decoration: TextDecoration.none,
))),
],
)
]),
)),
)
),
);
}
}