Unverified Commit 63c3de10 authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Timer picker fidelity revision (#38481)

* WIP

* trying out different numbers

* apply intrinsic width and height

* update

* update behavior

* documentation

* wip

* fix tests

* constants

* respect theme

* respect theme

* add new test

* add new test

* update

* review

* update golden commit hash
parent 476a4de1
ead5d5df3236f6d9e619e640029f9811e4eb0716 49f8198b72f6e12c65fe1db2e46162de0204e671
...@@ -104,22 +104,22 @@ const TextStyle _kDefaultPickerDarkTextStyle = TextStyle( ...@@ -104,22 +104,22 @@ const TextStyle _kDefaultPickerDarkTextStyle = TextStyle(
); );
// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/. // Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
const TextStyle _kDefaultDateTimePickerLightTextStyle = TextStyle( const TextStyle _kDefaultDateTimePickerLightTextStyle = TextStyle(
inherit: false, inherit: false,
fontFamily: '.SF Pro Display', fontFamily: '.SF Pro Display',
fontSize: 21, fontSize: 21,
fontWeight: FontWeight.w300, fontWeight: FontWeight.normal,
letterSpacing: -1.05,
color: CupertinoColors.black, color: CupertinoColors.black,
); );
// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/. // Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
const TextStyle _kDefaultDateTimePickerDarkTextStyle = TextStyle( const TextStyle _kDefaultDateTimePickerDarkTextStyle = TextStyle(
inherit: false, inherit: false,
fontFamily: '.SF Pro Display', fontFamily: '.SF Pro Display',
fontSize: 21, fontSize: 21,
fontWeight: FontWeight.w300, fontWeight: FontWeight.normal,
letterSpacing: -1.05,
color: CupertinoColors.white, color: CupertinoColors.white,
); );
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/semantics.dart'; import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -248,8 +249,8 @@ void main() { ...@@ -248,8 +249,8 @@ void main() {
width: 400.0, width: 400.0,
child: CupertinoTimerPicker( child: CupertinoTimerPicker(
minuteInterval: 10, minuteInterval: 10,
secondInterval: 15, secondInterval: 12,
initialTimerDuration: const Duration(hours: 10, minutes: 40, seconds: 45), initialTimerDuration: const Duration(hours: 10, minutes: 40, seconds: 48),
mode: CupertinoTimerPickerMode.hms, mode: CupertinoTimerPickerMode.hms,
onTimerDurationChanged: (Duration d) { onTimerDurationChanged: (Duration d) {
duration = d; duration = d;
...@@ -261,13 +262,13 @@ void main() { ...@@ -261,13 +262,13 @@ void main() {
await tester.drag(find.text('40'), _kRowOffset); await tester.drag(find.text('40'), _kRowOffset);
await tester.pump(); await tester.pump();
await tester.drag(find.text('45'), -_kRowOffset); await tester.drag(find.text('48'), -_kRowOffset);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
expect( expect(
duration, duration,
const Duration(hours: 10, minutes: 50, seconds: 30), const Duration(hours: 10, minutes: 50, seconds: 36),
); );
}); });
...@@ -905,7 +906,7 @@ void main() { ...@@ -905,7 +906,7 @@ void main() {
CupertinoApp( CupertinoApp(
home: Center( home: Center(
child: SizedBox( child: SizedBox(
width: 400, width: 500,
height: 400, height: 400,
child: RepaintBoundary( child: RepaintBoundary(
child: CupertinoDatePicker( child: CupertinoDatePicker(
...@@ -923,7 +924,7 @@ void main() { ...@@ -923,7 +924,7 @@ void main() {
find.byType(CupertinoDatePicker), find.byType(CupertinoDatePicker),
matchesGoldenFile( matchesGoldenFile(
'date_picker_test.datetime.initial.png', 'date_picker_test.datetime.initial.png',
version: 1, version: 2,
), ),
); );
...@@ -935,12 +936,142 @@ void main() { ...@@ -935,12 +936,142 @@ void main() {
find.byType(CupertinoDatePicker), find.byType(CupertinoDatePicker),
matchesGoldenFile( matchesGoldenFile(
'date_picker_test.datetime.drag.png', 'date_picker_test.datetime.drag.png',
version: 1, version: 2,
), ),
); );
}); });
}); });
testWidgets('TimerPicker golden tests', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
// Also check if the picker respects the theme.
theme: const CupertinoThemeData(
textTheme: CupertinoTextThemeData(
pickerTextStyle: TextStyle(
color: Color(0xFF663311),
),
),
),
home: Center(
child: SizedBox(
width: 320,
height: 216,
child: RepaintBoundary(
child: CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.hm,
initialTimerDuration: const Duration(hours: 23, minutes: 59),
onTimerDurationChanged: (_) {},
),
)
),
),
),
);
await expectLater(
find.byType(CupertinoTimerPicker),
matchesGoldenFile(
'timer_picker_test.datetime.initial.png',
version: 1,
),
);
// Slightly drag the minute component to make the current minute off-center.
await tester.drag(find.text('59'), Offset(0, _kRowOffset.dy / 2));
await tester.pump();
await expectLater(
find.byType(CupertinoTimerPicker),
matchesGoldenFile(
'timer_picker_test.datetime.drag.png',
version: 1,
),
);
});
testWidgets('TimerPicker only changes hour label after scrolling stops', (WidgetTester tester) async {
Duration duration;
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: SizedBox(
width: 320,
height: 216,
child: CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.hm,
initialTimerDuration: const Duration(hours: 2, minutes: 30),
onTimerDurationChanged: (Duration d) { duration = d; },
),
),
),
),
);
expect(duration, isNull);
expect(find.text('hour'), findsNothing);
expect(find.text('hours'), findsOneWidget);
await tester.drag(find.text('2'), Offset(0, -_kRowOffset.dy));
// Duration should change but not the label.
expect(duration?.inHours, 1);
expect(find.text('hour'), findsNothing);
expect(find.text('hours'), findsOneWidget);
await tester.pumpAndSettle();
// Now the label should change.
expect(duration?.inHours, 1);
expect(find.text('hours'), findsNothing);
expect(find.text('hour'), findsOneWidget);
});
testWidgets('TimerPicker has intrinsic width and height', (WidgetTester tester) async {
const Key key = Key('key');
await tester.pumpWidget(
CupertinoApp(
home: CupertinoTimerPicker(
key: key,
mode: CupertinoTimerPickerMode.hm,
initialTimerDuration: const Duration(hours: 2, minutes: 30),
onTimerDurationChanged: (Duration d) {},
),
),
);
expect(tester.getSize(find.descendant(of: find.byKey(key), matching: find.byType(Row))), const Size(320, 216));
// Different modes shouldn't share state.
await tester.pumpWidget(const Placeholder());
await tester.pumpWidget(
CupertinoApp(
home: CupertinoTimerPicker(
key: key,
mode: CupertinoTimerPickerMode.ms,
initialTimerDuration: const Duration(minutes: 30, seconds: 3),
onTimerDurationChanged: (Duration d) {},
),
),
);
expect(tester.getSize(find.descendant(of: find.byKey(key), matching: find.byType(Row))), const Size(320, 216));
// Different modes shouldn't share state.
await tester.pumpWidget(const Placeholder());
await tester.pumpWidget(
CupertinoApp(
home: CupertinoTimerPicker(
key: key,
mode: CupertinoTimerPickerMode.hms,
initialTimerDuration: const Duration(hours: 5, minutes: 17, seconds: 19),
onTimerDurationChanged: (Duration d) {},
),
),
);
expect(tester.getSize(find.descendant(of: find.byKey(key), matching: find.byType(Row))), const Size(330, 216));
});
testWidgets('scrollController can be removed or added', (WidgetTester tester) async { testWidgets('scrollController can be removed or added', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics(); final SemanticsHandle handle = tester.ensureSemantics();
int lastSelectedItem; int lastSelectedItem;
......
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