Skip to content

Commit bd055cf

Browse files
authored
Add missing space between DayPeriodControl and time control in time picker (flutter#162230)
<!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> Fixes flutter#162229 | Before | After | |--------|--------| | ![Simulator Screenshot - iPhone 14 Pro - 2025-01-26 at 22 01 55](https://github.com/user-attachments/assets/99034ccf-7006-44d9-9642-3ceb1ffd4fb5) ![Simulator Screenshot - iPhone 14 Pro - 2025-01-27 at 16 17 16](https://github.com/user-attachments/assets/93b233ec-e66f-4d06-bdd6-474a841dc1a8) | ![Simulator Screenshot - iPhone 14 Pro - 2025-01-26 at 21 59 04](https://github.com/user-attachments/assets/319e6c83-c63a-4415-8d19-62359b0a93a0) ![Simulator Screenshot - iPhone 14 Pro - 2025-01-27 at 16 17 42](https://github.com/user-attachments/assets/4753b5c6-46f5-4b21-80ef-bc568364198e) | ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent 29a2f67 commit bd055cf

File tree

2 files changed

+75
-30
lines changed

2 files changed

+75
-30
lines changed

packages/flutter/lib/src/material/time_picker.dart

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,12 @@ class _TimePickerHeader extends StatelessWidget {
267267
),
268268
),
269269
Row(
270+
textDirection:
271+
timeOfDayFormat == TimeOfDayFormat.a_space_h_colon_mm
272+
? TextDirection.rtl
273+
: TextDirection.ltr,
274+
spacing: 12,
270275
children: <Widget>[
271-
if (hourDialType == _HourDialType.twelveHour &&
272-
timeOfDayFormat == TimeOfDayFormat.a_space_h_colon_mm)
273-
const _DayPeriodControl(),
274276
Expanded(
275277
child: Row(
276278
// Hour/minutes should not change positions in RTL locales.
@@ -282,11 +284,7 @@ class _TimePickerHeader extends StatelessWidget {
282284
],
283285
),
284286
),
285-
if (hourDialType == _HourDialType.twelveHour &&
286-
timeOfDayFormat != TimeOfDayFormat.a_space_h_colon_mm) ...<Widget>[
287-
const SizedBox(width: 12),
288-
const _DayPeriodControl(),
289-
],
287+
if (hourDialType == _HourDialType.twelveHour) const _DayPeriodControl(),
290288
],
291289
),
292290
],
@@ -303,29 +301,24 @@ class _TimePickerHeader extends StatelessWidget {
303301
_TimePickerModel.defaultThemeOf(context).helpTextStyle,
304302
),
305303
Column(
304+
verticalDirection:
305+
timeOfDayFormat == TimeOfDayFormat.a_space_h_colon_mm
306+
? VerticalDirection.up
307+
: VerticalDirection.down,
306308
mainAxisAlignment: MainAxisAlignment.center,
307309
crossAxisAlignment: CrossAxisAlignment.start,
310+
spacing: 12,
308311
children: <Widget>[
309-
if (hourDialType == _HourDialType.twelveHour &&
310-
timeOfDayFormat == TimeOfDayFormat.a_space_h_colon_mm)
311-
const _DayPeriodControl(),
312-
Padding(
313-
padding: EdgeInsets.only(
314-
bottom: hourDialType == _HourDialType.twelveHour ? 12 : 0,
315-
),
316-
child: Row(
317-
// Hour/minutes should not change positions in RTL locales.
318-
textDirection: TextDirection.ltr,
319-
children: <Widget>[
320-
const Expanded(child: _HourControl()),
321-
_TimeSelectorSeparator(timeOfDayFormat: timeOfDayFormat),
322-
const Expanded(child: _MinuteControl()),
323-
],
324-
),
312+
Row(
313+
// Hour/minutes should not change positions in RTL locales.
314+
textDirection: TextDirection.ltr,
315+
children: <Widget>[
316+
const Expanded(child: _HourControl()),
317+
_TimeSelectorSeparator(timeOfDayFormat: timeOfDayFormat),
318+
const Expanded(child: _MinuteControl()),
319+
],
325320
),
326-
if (hourDialType == _HourDialType.twelveHour &&
327-
timeOfDayFormat != TimeOfDayFormat.a_space_h_colon_mm)
328-
const _DayPeriodControl(),
321+
if (hourDialType == _HourDialType.twelveHour) const _DayPeriodControl(),
329322
],
330323
),
331324
],

packages/flutter/test/material/time_picker_test.dart

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'dart:ui';
1010

1111
import 'package:flutter/material.dart';
1212
import 'package:flutter/rendering.dart';
13+
import 'package:flutter_localizations/flutter_localizations.dart';
1314
import 'package:flutter_test/flutter_test.dart';
1415

1516
import '../widgets/feedback_tester.dart';
@@ -2162,6 +2163,56 @@ void main() {
21622163

21632164
expect(tester.getSize(findBorderPainter().first), const Size(96.0, 70.0));
21642165
});
2166+
2167+
// Regression test for https://github.com/flutter/flutter/issues/162229.
2168+
testWidgets(
2169+
'Time picker spacing between time control and day period control for locales using "a h:mm" pattern',
2170+
(WidgetTester tester) async {
2171+
addTearDown(tester.view.reset);
2172+
2173+
final Finder dayPeriodControlFinder = find.byWidgetPredicate(
2174+
(Widget w) => '${w.runtimeType}' == '_DayPeriodControl',
2175+
);
2176+
final Finder timeControlFinder =
2177+
find.ancestor(of: find.text('7'), matching: find.byType(Row)).first;
2178+
2179+
// Render in portrait mode.
2180+
tester.view.physicalSize = const Size(800, 800.5);
2181+
tester.view.devicePixelRatio = 1;
2182+
await mediaQueryBoilerplate(
2183+
tester,
2184+
materialType: MaterialType.material3,
2185+
locale: const Locale('ko', 'KR'),
2186+
);
2187+
2188+
expect(
2189+
tester.getBottomLeft(timeControlFinder).dx -
2190+
tester.getBottomRight(dayPeriodControlFinder).dx,
2191+
12,
2192+
);
2193+
2194+
// Dismiss the dialog.
2195+
final MaterialLocalizations materialLocalizations = MaterialLocalizations.of(
2196+
tester.element(find.byType(TextButton).first),
2197+
);
2198+
await tester.tap(find.text(materialLocalizations.okButtonLabel));
2199+
await tester.pumpAndSettle();
2200+
2201+
// Render in landscape mode.
2202+
tester.view.physicalSize = const Size(800.5, 800);
2203+
tester.view.devicePixelRatio = 1;
2204+
await mediaQueryBoilerplate(
2205+
tester,
2206+
materialType: MaterialType.material3,
2207+
locale: const Locale('ko', 'KR'),
2208+
);
2209+
2210+
expect(
2211+
tester.getTopLeft(timeControlFinder).dy - tester.getBottomLeft(dayPeriodControlFinder).dy,
2212+
12,
2213+
);
2214+
},
2215+
);
21652216
}
21662217

21672218
final Finder findDialPaint = find.descendant(
@@ -2204,15 +2255,16 @@ Future<void> mediaQueryBoilerplate(
22042255
bool tapButton = true,
22052256
required MaterialType materialType,
22062257
Orientation? orientation,
2258+
Locale locale = const Locale('en', 'US'),
22072259
}) async {
22082260
await tester.pumpWidget(
22092261
Theme(
22102262
data: ThemeData(useMaterial3: materialType == MaterialType.material3),
22112263
child: Localizations(
2212-
locale: const Locale('en', 'US'),
2264+
locale: locale,
22132265
delegates: const <LocalizationsDelegate<dynamic>>[
2214-
DefaultMaterialLocalizations.delegate,
2215-
DefaultWidgetsLocalizations.delegate,
2266+
GlobalMaterialLocalizations.delegate,
2267+
GlobalWidgetsLocalizations.delegate,
22162268
],
22172269
child: MediaQuery(
22182270
data: MediaQueryData(

0 commit comments

Comments
 (0)