mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Feat: Add opportunity to change CupertinoTextField suffix alignment (#154601)
Fixes #152482
This commit is contained in:
parent
b05246d305
commit
6bba08cbcc
@ -239,6 +239,7 @@ class CupertinoTextField extends StatefulWidget {
|
|||||||
this.prefixMode = OverlayVisibilityMode.always,
|
this.prefixMode = OverlayVisibilityMode.always,
|
||||||
this.suffix,
|
this.suffix,
|
||||||
this.suffixMode = OverlayVisibilityMode.always,
|
this.suffixMode = OverlayVisibilityMode.always,
|
||||||
|
this.crossAxisAlignment = CrossAxisAlignment.center,
|
||||||
this.clearButtonMode = OverlayVisibilityMode.never,
|
this.clearButtonMode = OverlayVisibilityMode.never,
|
||||||
this.clearButtonSemanticLabel,
|
this.clearButtonSemanticLabel,
|
||||||
TextInputType? keyboardType,
|
TextInputType? keyboardType,
|
||||||
@ -367,6 +368,7 @@ class CupertinoTextField extends StatefulWidget {
|
|||||||
this.prefixMode = OverlayVisibilityMode.always,
|
this.prefixMode = OverlayVisibilityMode.always,
|
||||||
this.suffix,
|
this.suffix,
|
||||||
this.suffixMode = OverlayVisibilityMode.always,
|
this.suffixMode = OverlayVisibilityMode.always,
|
||||||
|
this.crossAxisAlignment = CrossAxisAlignment.center,
|
||||||
this.clearButtonMode = OverlayVisibilityMode.never,
|
this.clearButtonMode = OverlayVisibilityMode.never,
|
||||||
this.clearButtonSemanticLabel,
|
this.clearButtonSemanticLabel,
|
||||||
TextInputType? keyboardType,
|
TextInputType? keyboardType,
|
||||||
@ -516,6 +518,13 @@ class CupertinoTextField extends StatefulWidget {
|
|||||||
/// Has no effect when [suffix] is null.
|
/// Has no effect when [suffix] is null.
|
||||||
final OverlayVisibilityMode suffixMode;
|
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.
|
/// Show an iOS-style clear button to clear the current text entry.
|
||||||
///
|
///
|
||||||
/// Can be made to appear depending on various text states of the
|
/// Can be made to appear depending on various text states of the
|
||||||
@ -1213,28 +1222,31 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
|
|||||||
(true, true) => widget.suffix ?? _buildClearButton(),
|
(true, true) => widget.suffix ?? _buildClearButton(),
|
||||||
(false, true) => _buildClearButton(),
|
(false, true) => _buildClearButton(),
|
||||||
};
|
};
|
||||||
return Row(children: <Widget>[
|
return Row(
|
||||||
// Insert a prefix at the front if the prefix visibility mode matches
|
crossAxisAlignment: widget.crossAxisAlignment,
|
||||||
// the current text state.
|
children: <Widget>[
|
||||||
if (prefixWidget != null) prefixWidget,
|
// Insert a prefix at the front if the prefix visibility mode matches
|
||||||
// In the middle part, stack the placeholder on top of the main EditableText
|
// the current text state.
|
||||||
// if needed.
|
if (prefixWidget != null) prefixWidget,
|
||||||
Expanded(
|
// In the middle part, stack the placeholder on top of the main EditableText
|
||||||
child: Stack(
|
// if needed.
|
||||||
// Ideally this should be baseline aligned. However that comes at
|
Expanded(
|
||||||
// the cost of the ability to compute the intrinsic dimensions of
|
child: Stack(
|
||||||
// this widget.
|
// Ideally this should be baseline aligned. However that comes at
|
||||||
// See also https://github.com/flutter/flutter/issues/13715.
|
// the cost of the ability to compute the intrinsic dimensions of
|
||||||
alignment: AlignmentDirectional.center,
|
// this widget.
|
||||||
textDirection: widget.textDirection,
|
// See also https://github.com/flutter/flutter/issues/13715.
|
||||||
children: <Widget>[
|
alignment: AlignmentDirectional.center,
|
||||||
if (placeholder != null) placeholder,
|
textDirection: widget.textDirection,
|
||||||
editableText,
|
children: <Widget>[
|
||||||
],
|
if (placeholder != null) placeholder,
|
||||||
|
editableText,
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if (suffixWidget != null) suffixWidget,
|
||||||
if (suffixWidget != null) suffixWidget
|
],
|
||||||
]);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
testWidgets('text selection style 1', (WidgetTester tester) async {
|
||||||
final TextEditingController controller = TextEditingController(
|
final TextEditingController controller = TextEditingController(
|
||||||
text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!',
|
text: 'Atwater Peel Sherbrooke Bonaventure\nhi\nwassssup!',
|
||||||
|
Loading…
Reference in New Issue
Block a user