Unverified Commit 32b9af69 authored by Jacek Marchwicki's avatar Jacek Marchwicki Committed by GitHub

Use the correct pleace for the system navigation bar color adjustment (#68102)

parent e444b1e3
...@@ -244,9 +244,47 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> ...@@ -244,9 +244,47 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
} }
void _updateSystemChrome() { void _updateSystemChrome() {
// Take overlay style from the place where a system status bar and system
// navigation bar are placed to update system style overlay.
// The center of the system navigation bar and the center of the status bar
// are used to get SystemUiOverlayStyle's to update system overlay appearance.
//
// Horizontal center of the screen
// V
// ++++++++++++++++++++++++++
// | |
// | System status bar | <- Vertical center of the status bar
// | |
// ++++++++++++++++++++++++++
// | |
// | Content |
// ~ ~
// | |
// ++++++++++++++++++++++++++
// | |
// | System navigation bar | <- Vertical center of the navigation bar
// | |
// ++++++++++++++++++++++++++ <- bounds.bottom
final Rect bounds = paintBounds; final Rect bounds = paintBounds;
final Offset top = Offset(bounds.center.dx, _window.padding.top / _window.devicePixelRatio); // Center of the status bar
final Offset bottom = Offset(bounds.center.dx, bounds.center.dy - _window.padding.bottom / _window.devicePixelRatio); final Offset top = Offset(
// Horizontal center of the screen
bounds.center.dx,
// The vertical center of the system status bar. The system status bar
// height is kept as top window padding.
_window.padding.top / 2.0,
);
// Center of the navigation bar
final Offset bottom = Offset(
// Horizontal center of the screen
bounds.center.dx,
// Vertical center of the system navigation bar. The system navigation bar
// height is kept as bottom window padding. The "1" needs to be subtracted
// from the bottom because available pixels are in (0..bottom) range.
// I.e. for a device with 1920 height, bound.bottom is 1920, but the most
// bottom drawn pixel is at 1919 position.
bounds.bottom - 1.0 - _window.padding.bottom / 2.0,
);
final SystemUiOverlayStyle? upperOverlayStyle = layer!.find<SystemUiOverlayStyle>(top); final SystemUiOverlayStyle? upperOverlayStyle = layer!.find<SystemUiOverlayStyle>(top);
// Only android has a customizable system navigation bar. // Only android has a customizable system navigation bar.
SystemUiOverlayStyle? lowerOverlayStyle; SystemUiOverlayStyle? lowerOverlayStyle;
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('SystemChrome - style', () {
const double statusBarHeight = 25.0;
const double navigationBarHeight = 54.0;
const double deviceHeight = 960.0;
const double deviceWidth = 480.0;
const double devicePixelRatio = 2.0;
void setupTestDevice() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
const FakeWindowPadding padding = FakeWindowPadding(
top: statusBarHeight * devicePixelRatio,
bottom: navigationBarHeight * devicePixelRatio,
);
binding.window
..viewPaddingTestValue = padding
..paddingTestValue = padding
..devicePixelRatioTestValue = devicePixelRatio
..physicalSizeTestValue = const Size(
deviceWidth * devicePixelRatio,
deviceHeight * devicePixelRatio,
);
}
tearDown(() async {
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle());
await pumpEventQueue();
});
group('status bar', () {
testWidgets(
'statusBarColor isn\'t set for unannotated view',
(WidgetTester tester) async {
await tester.pumpWidget(const SizedBox.expand());
await tester.pumpAndSettle();
expect(SystemChrome.latestStyle?.statusBarColor, isNull);
},
);
testWidgets(
'statusBarColor is set for annotated view',
(WidgetTester tester) async {
setupTestDevice();
await tester.pumpWidget(const AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.blue,
),
child: SizedBox.expand(),
));
await tester.pumpAndSettle();
expect(
SystemChrome.latestStyle?.statusBarColor,
Colors.blue,
);
},
variant: TargetPlatformVariant.mobile(),
);
testWidgets(
'statusBarColor isn\'t set when view covers less than half of the system status bar',
(WidgetTester tester) async {
setupTestDevice();
const double lessThanHalfOfTheStatusBarHeight =
statusBarHeight / 2.0 - 1;
await tester.pumpWidget(const Align(
alignment: Alignment.topCenter,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.blue,
),
child: SizedBox(
width: 100,
height: lessThanHalfOfTheStatusBarHeight,
),
),
));
await tester.pumpAndSettle();
expect(SystemChrome.latestStyle?.statusBarColor, isNull);
},
variant: TargetPlatformVariant.mobile(),
);
testWidgets(
'statusBarColor is set when view covers more than half of tye system status bar',
(WidgetTester tester) async {
setupTestDevice();
const double moreThanHalfOfTheStatusBarHeight =
statusBarHeight / 2.0 + 1;
await tester.pumpWidget(const Align(
alignment: Alignment.topCenter,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.blue,
),
child: SizedBox(
width: 100,
height: moreThanHalfOfTheStatusBarHeight,
),
),
));
await tester.pumpAndSettle();
expect(
SystemChrome.latestStyle?.statusBarColor,
Colors.blue,
);
},
variant: TargetPlatformVariant.mobile(),
);
});
group('navigation color (Android only)', () {
testWidgets(
'systemNavigationBarColor isn\'t set for non Android device',
(WidgetTester tester) async {
setupTestDevice();
await tester.pumpWidget(const AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.blue,
),
child: SizedBox.expand(),
));
await tester.pumpAndSettle();
expect(
SystemChrome.latestStyle?.systemNavigationBarColor,
isNull,
);
},
variant: TargetPlatformVariant.only(TargetPlatform.iOS),
);
testWidgets(
'systemNavigationBarColor isn\'t set for unannotated view',
(WidgetTester tester) async {
await tester.pumpWidget(const SizedBox.expand());
await tester.pumpAndSettle();
expect(SystemChrome.latestStyle?.systemNavigationBarColor, isNull);
},
variant: TargetPlatformVariant.only(TargetPlatform.android),
);
testWidgets(
'systemNavigationBarColor is set for annotated view',
(WidgetTester tester) async {
setupTestDevice();
await tester.pumpWidget(const AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.blue,
),
child: SizedBox.expand(),
));
await tester.pumpAndSettle();
expect(
SystemChrome.latestStyle?.systemNavigationBarColor,
Colors.blue,
);
},
variant: TargetPlatformVariant.only(TargetPlatform.android),
);
testWidgets(
'systemNavigationBarColor isn\'t set when view covers less than half of navigation bar',
(WidgetTester tester) async {
setupTestDevice();
const double lessThanHalfOfTheNavigationBarHeight =
navigationBarHeight / 2.0 - 1;
await tester.pumpWidget(const Align(
alignment: Alignment.bottomCenter,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.blue,
),
child: SizedBox(
width: 100,
height: lessThanHalfOfTheNavigationBarHeight,
),
),
));
await tester.pumpAndSettle();
expect(SystemChrome.latestStyle?.systemNavigationBarColor, isNull);
},
variant: TargetPlatformVariant.only(TargetPlatform.android),
);
testWidgets(
'systemNavigationBarColor is set when view covers more than half of navigation bar',
(WidgetTester tester) async {
setupTestDevice();
const double moreThanHalfOfTheNavigationBarHeight =
navigationBarHeight / 2.0 + 1;
await tester.pumpWidget(const Align(
alignment: Alignment.bottomCenter,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.blue,
),
child: SizedBox(
width: 100,
height: moreThanHalfOfTheNavigationBarHeight,
),
),
));
await tester.pumpAndSettle();
expect(
SystemChrome.latestStyle?.systemNavigationBarColor,
Colors.blue,
);
},
variant: TargetPlatformVariant.only(TargetPlatform.android),
);
});
});
}
class FakeWindowPadding implements WindowPadding {
const FakeWindowPadding({
this.left = 0.0,
this.top = 0.0,
this.right = 0.0,
this.bottom = 0.0,
});
@override
final double left;
@override
final double top;
@override
final double right;
@override
final double bottom;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment