mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Use the correct pleace for the system navigation bar color adjustment (#68102)
This commit is contained in:
parent
e444b1e3fa
commit
32b9af6996
@ -244,9 +244,47 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
||||
}
|
||||
|
||||
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 Offset top = Offset(bounds.center.dx, _window.padding.top / _window.devicePixelRatio);
|
||||
final Offset bottom = Offset(bounds.center.dx, bounds.center.dy - _window.padding.bottom / _window.devicePixelRatio);
|
||||
// Center of the status bar
|
||||
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);
|
||||
// Only android has a customizable system navigation bar.
|
||||
SystemUiOverlayStyle? lowerOverlayStyle;
|
||||
|
253
packages/flutter/test/rendering/view_chrome_style_test.dart
Normal file
253
packages/flutter/test/rendering/view_chrome_style_test.dart
Normal file
@ -0,0 +1,253 @@
|
||||
// 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user