mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Always relies on floatingLabelStyle when FloatingLabelBehavior.always (#147374)
## Description With this PR, when `InputDecorator.floatingLabelBehavior` is set to `FloatingLabelBehavior.always` the label style is always set to `InputDecorator.floatingLabelStyle`, previously `InputDecorator.labelStyle` was used when the field was not focused or was empty. ## Related Issue Fixes https://github.com/flutter/flutter/issues/147231 ## Tests Adds 1 test for this particular issue and several missing tests.
This commit is contained in:
parent
f1037a01b7
commit
99876ba2ce
@ -1828,8 +1828,11 @@ class InputDecorator extends StatefulWidget {
|
||||
/// Whether the label needs to get out of the way of the input, either by
|
||||
/// floating or disappearing.
|
||||
///
|
||||
/// Will withdraw when not empty, or when focused while enabled.
|
||||
bool get _labelShouldWithdraw => !isEmpty || (isFocused && decoration.enabled);
|
||||
/// Will withdraw when not empty, when focused while enabled, or when
|
||||
/// floating behavior is [FloatingLabelBehavior.always].
|
||||
bool get _labelShouldWithdraw => !isEmpty
|
||||
|| (isFocused && decoration.enabled)
|
||||
|| decoration.floatingLabelBehavior == FloatingLabelBehavior.always;
|
||||
|
||||
@override
|
||||
State<InputDecorator> createState() => _InputDecoratorState();
|
||||
@ -1872,9 +1875,8 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final bool labelIsInitiallyFloating = widget.decoration.floatingLabelBehavior == FloatingLabelBehavior.always
|
||||
|| (widget.decoration.floatingLabelBehavior != FloatingLabelBehavior.never &&
|
||||
widget._labelShouldWithdraw);
|
||||
final bool labelIsInitiallyFloating = widget.decoration.floatingLabelBehavior != FloatingLabelBehavior.never
|
||||
&& widget._labelShouldWithdraw;
|
||||
|
||||
_floatingLabelController = AnimationController(
|
||||
duration: _kTransitionDuration,
|
||||
@ -1937,8 +1939,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
final bool floatBehaviorChanged = widget.decoration.floatingLabelBehavior != old.decoration.floatingLabelBehavior;
|
||||
|
||||
if (widget._labelShouldWithdraw != old._labelShouldWithdraw || floatBehaviorChanged) {
|
||||
if (_floatingLabelEnabled
|
||||
&& (widget._labelShouldWithdraw || widget.decoration.floatingLabelBehavior == FloatingLabelBehavior.always)) {
|
||||
if (_floatingLabelEnabled && widget._labelShouldWithdraw) {
|
||||
_floatingLabelController.forward();
|
||||
} else {
|
||||
_floatingLabelController.reverse();
|
||||
@ -2028,8 +2029,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
// hint would.
|
||||
bool get _hasInlineLabel {
|
||||
return !widget._labelShouldWithdraw
|
||||
&& (decoration.labelText != null || decoration.label != null)
|
||||
&& decoration.floatingLabelBehavior != FloatingLabelBehavior.always;
|
||||
&& (decoration.labelText != null || decoration.label != null);
|
||||
}
|
||||
|
||||
// If the label is a floating placeholder, it's always shown.
|
||||
|
||||
@ -2032,6 +2032,137 @@ void main() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('floatingLabelStyle overrides default style', (WidgetTester tester) async {
|
||||
const TextStyle floatingLabelStyle = TextStyle(color: Colors.indigo, fontSize: 16.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
isFocused: true, // Label appears floating above input field.
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
floatingLabelStyle: floatingLabelStyle,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, floatingLabelStyle.color);
|
||||
expect(getLabelStyle(tester).fontSize, floatingLabelStyle.fontSize);
|
||||
});
|
||||
|
||||
testWidgets('floatingLabelStyle defaults to labelStyle', (WidgetTester tester) async {
|
||||
const TextStyle labelStyle = TextStyle(color: Colors.amber, fontSize: 16.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
isFocused: true, // Label appears floating above input field.
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
labelStyle: labelStyle,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, labelStyle.color);
|
||||
expect(getLabelStyle(tester).fontSize, labelStyle.fontSize);
|
||||
});
|
||||
|
||||
testWidgets('floatingLabelStyle takes precedence over labelStyle', (WidgetTester tester) async {
|
||||
const TextStyle labelStyle = TextStyle(color: Colors.amber, fontSize: 16.0);
|
||||
const TextStyle floatingLabelStyle = TextStyle(color: Colors.indigo, fontSize: 16.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
isFocused: true, // Label appears floating above input field.
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
labelStyle: labelStyle,
|
||||
floatingLabelStyle: floatingLabelStyle,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, floatingLabelStyle.color);
|
||||
expect(getLabelStyle(tester).fontSize, floatingLabelStyle.fontSize);
|
||||
});
|
||||
|
||||
testWidgets('InputDecorationTheme labelStyle overrides default style', (WidgetTester tester) async {
|
||||
const TextStyle labelStyle = TextStyle(color: Colors.amber, fontSize: 16.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true, // Label appears inline, on top of the input field.
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
labelStyle: labelStyle,
|
||||
),
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, labelStyle.color);
|
||||
});
|
||||
|
||||
testWidgets('InputDecorationTheme floatingLabelStyle overrides default style', (WidgetTester tester) async {
|
||||
const TextStyle floatingLabelStyle = TextStyle(color: Colors.indigo, fontSize: 16.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
isFocused: true, // Label appears floating above input field.
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
floatingLabelStyle: floatingLabelStyle,
|
||||
),
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, floatingLabelStyle.color);
|
||||
});
|
||||
|
||||
testWidgets('floatingLabelStyle is always used when FloatingLabelBehavior.always', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/147231.
|
||||
const TextStyle labelStyle = TextStyle(color: Colors.amber, fontSize: 16.0);
|
||||
const TextStyle floatingLabelStyle = TextStyle(color: Colors.indigo, fontSize: 16.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
labelStyle: labelStyle,
|
||||
floatingLabelStyle: floatingLabelStyle,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, floatingLabelStyle.color);
|
||||
expect(getLabelStyle(tester).fontSize, floatingLabelStyle.fontSize);
|
||||
|
||||
// Focus the input decorator.
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
isFocused: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: labelText,
|
||||
labelStyle: labelStyle,
|
||||
floatingLabelStyle: floatingLabelStyle,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(getLabelStyle(tester).color, floatingLabelStyle.color);
|
||||
expect(getLabelStyle(tester).fontSize, floatingLabelStyle.fontSize);
|
||||
});
|
||||
});
|
||||
|
||||
group('Material3 - InputDecoration labelText layout', () {
|
||||
@ -4915,6 +5046,49 @@ void main() {
|
||||
expect(getOpacity(tester, prefixText), 1.0);
|
||||
});
|
||||
|
||||
testWidgets('Prefix and suffix are not visible when decorator is empty', (WidgetTester tester) async {
|
||||
const String prefixText = 'Prefix';
|
||||
const String suffixText = 'Suffix';
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
decoration: const InputDecoration(
|
||||
filled: true,
|
||||
labelText: labelText,
|
||||
prefixText: prefixText,
|
||||
suffixText: suffixText,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Prefix and suffix are hidden.
|
||||
expect(getOpacity(tester, prefixText), 0.0);
|
||||
expect(getOpacity(tester, suffixText), 0.0);
|
||||
});
|
||||
|
||||
testWidgets('Prefix and suffix are visible when decorator is empty and floating behavior is FloatingBehavior.always', (WidgetTester tester) async {
|
||||
const String prefixText = 'Prefix';
|
||||
const String suffixText = 'Suffix';
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
isEmpty: true,
|
||||
decoration: const InputDecoration(
|
||||
filled: true,
|
||||
labelText: labelText,
|
||||
prefixText: prefixText,
|
||||
suffixText: suffixText,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Prefix and suffix are visible.
|
||||
expect(getOpacity(tester, prefixText), 1.0);
|
||||
expect(getOpacity(tester, suffixText), 1.0);
|
||||
});
|
||||
|
||||
testWidgets('OutlineInputBorder and InputDecorator long labels and in Floating, the width should ignore the icon width', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/64427.
|
||||
const String labelText = 'Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user