Skip to content

Commit

Permalink
Feat: Add opportunity to change CupertinoTextField suffix alignment (f…
Browse files Browse the repository at this point in the history
  • Loading branch information
ziqq authored Oct 1, 2024
1 parent b05246d commit 6bba08c
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 21 deletions.
54 changes: 33 additions & 21 deletions packages/flutter/lib/src/cupertino/text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class CupertinoTextField extends StatefulWidget {
this.prefixMode = OverlayVisibilityMode.always,
this.suffix,
this.suffixMode = OverlayVisibilityMode.always,
this.crossAxisAlignment = CrossAxisAlignment.center,
this.clearButtonMode = OverlayVisibilityMode.never,
this.clearButtonSemanticLabel,
TextInputType? keyboardType,
Expand Down Expand Up @@ -367,6 +368,7 @@ class CupertinoTextField extends StatefulWidget {
this.prefixMode = OverlayVisibilityMode.always,
this.suffix,
this.suffixMode = OverlayVisibilityMode.always,
this.crossAxisAlignment = CrossAxisAlignment.center,
this.clearButtonMode = OverlayVisibilityMode.never,
this.clearButtonSemanticLabel,
TextInputType? keyboardType,
Expand Down Expand Up @@ -516,6 +518,13 @@ class CupertinoTextField extends StatefulWidget {
/// Has no effect when [suffix] is null.
final OverlayVisibilityMode suffixMode;

/// Controls the vertical alignment of the [prefix] and the [suffix] widget in relation to content.
///
/// Defaults to [CrossAxisAlignment.center].
///
/// Has no effect when both the [prefix] and [suffix] are null.
final CrossAxisAlignment crossAxisAlignment;

/// Show an iOS-style clear button to clear the current text entry.
///
/// Can be made to appear depending on various text states of the
Expand Down Expand Up @@ -1213,28 +1222,31 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
(true, true) => widget.suffix ?? _buildClearButton(),
(false, true) => _buildClearButton(),
};
return Row(children: <Widget>[
// Insert a prefix at the front if the prefix visibility mode matches
// the current text state.
if (prefixWidget != null) prefixWidget,
// In the middle part, stack the placeholder on top of the main EditableText
// if needed.
Expanded(
child: Stack(
// Ideally this should be baseline aligned. However that comes at
// the cost of the ability to compute the intrinsic dimensions of
// this widget.
// See also https://github.com/flutter/flutter/issues/13715.
alignment: AlignmentDirectional.center,
textDirection: widget.textDirection,
children: <Widget>[
if (placeholder != null) placeholder,
editableText,
],
return Row(
crossAxisAlignment: widget.crossAxisAlignment,
children: <Widget>[
// Insert a prefix at the front if the prefix visibility mode matches
// the current text state.
if (prefixWidget != null) prefixWidget,
// In the middle part, stack the placeholder on top of the main EditableText
// if needed.
Expanded(
child: Stack(
// Ideally this should be baseline aligned. However that comes at
// the cost of the ability to compute the intrinsic dimensions of
// this widget.
// See also https://github.com/flutter/flutter/issues/13715.
alignment: AlignmentDirectional.center,
textDirection: widget.textDirection,
children: <Widget>[
if (placeholder != null) placeholder,
editableText,
],
),
),
),
if (suffixWidget != null) suffixWidget
]);
if (suffixWidget != null) suffixWidget,
],
);
},
);
}
Expand Down
67 changes: 67 additions & 0 deletions packages/flutter/test/cupertino/text_field_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8067,6 +8067,73 @@ void main() {
);
});

testWidgets(
'CrossAxisAlignment start positions the prefix and suffix at the top of the field',
(WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoTextField(
padding: EdgeInsets.zero, // Preventing delta position.dy
prefix: Icon(CupertinoIcons.add),
suffix: Icon(CupertinoIcons.clear),
crossAxisAlignment: CrossAxisAlignment.start,
),
),
),
);

final CupertinoTextField cupertinoTextField = tester.widget<CupertinoTextField>(
find.byType(CupertinoTextField),
);

expect(find.widgetWithIcon(CupertinoTextField, CupertinoIcons.clear), findsOneWidget);
expect(find.widgetWithIcon(CupertinoTextField, CupertinoIcons.add), findsOneWidget);
expect(cupertinoTextField.crossAxisAlignment, CrossAxisAlignment.start);

final double editableDy = tester.getTopLeft(find.byType(EditableText)).dy;
final double prefixDy = tester.getTopLeft(find.byIcon(CupertinoIcons.add)).dy;
final double suffixDy = tester.getTopLeft(find.byIcon(CupertinoIcons.clear)).dy;

expect(prefixDy, editableDy);
expect(suffixDy, editableDy);
},
);

testWidgets(
'CrossAxisAlignment end positions the prefix and suffix at the bottom of the field',
(WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoTextField(
padding: EdgeInsets.zero, // Preventing delta position.dy
prefix: SizedBox.square(dimension: 48, child: Icon(CupertinoIcons.add)),
suffix: SizedBox.square(dimension: 48, child: Icon(CupertinoIcons.clear)),
crossAxisAlignment: CrossAxisAlignment.end,
),
),
),
);

final CupertinoTextField cupertinoTextField = tester.widget<CupertinoTextField>(
find.byType(CupertinoTextField),
);

expect(find.widgetWithIcon(CupertinoTextField, CupertinoIcons.clear), findsOneWidget);
expect(find.widgetWithIcon(CupertinoTextField, CupertinoIcons.add), findsOneWidget);
expect(cupertinoTextField.crossAxisAlignment, CrossAxisAlignment.end);


final double editableDy = tester.getTopLeft(find.byType(EditableText)).dy;
final double prefixDy = tester.getTopLeft(find.byIcon(CupertinoIcons.add)).dy;
final double suffixDy = tester.getTopLeft(find.byIcon(CupertinoIcons.clear)).dy;

expect(prefixDy, lessThan(editableDy));
expect(suffixDy, lessThan(editableDy));
},
);

testWidgets('text selection style 1', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!',
Expand Down

0 comments on commit 6bba08c

Please sign in to comment.