Repository navigation
feat: Add hint (Widget) property to InputDecoration - #161424
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
|
cc: @justinmc |
|
Hey @maheshj01! 👋 |
|
@bleroux renamed. |
hint (Widget) property to InputDecoration
bleroux
left a comment
There was a problem hiding this comment.
Yes, tests are required for this PR.
I see a minimum of two tests:
- one which uses the new fields and check that the corresponding widget is used.
- another which check that defining both hint and hintText triggers the assert.
justinmc
left a comment
There was a problem hiding this comment.
Just a few minor points here.
| if (decoration.hint != null || hintText != null) { | ||
| final Widget hintWidget; | ||
| hintWidget = | ||
| decoration.hint ?? |
| final Widget hintWidget; | ||
| hintWidget = |
There was a problem hiding this comment.
This should be one line I think.
There was a problem hiding this comment.
Dart format makes it two liner, I suspect the analyzer test would fail making it one line
There was a problem hiding this comment.
Justin suggestion was related to merging the declaration and the initialization on the same line:
| final Widget hintWidget; | |
| hintWidget = | |
| final Widget hintWidget = |
There was a problem hiding this comment.
I have updated it with one line now
| /// or (b) the input has the focus. | ||
| final String? hintText; | ||
|
|
||
| /// The widget to use inplace of the [hintText]. Either [hintText] or |
There was a problem hiding this comment.
Also, the second sentence should be its own paragraph. From the style guide:
"The first paragraph of any dartdoc section must be a short self-contained sentence that explains the purpose and meaning of the item being documented. "
justinmc
left a comment
There was a problem hiding this comment.
One more small formatting thing in your docs here that needs to be fixed. Sorry, this should be part of the autoformatter or something.
| 'Declaring both label and labelText is not supported.', | ||
| ), | ||
| assert( | ||
| !(hintText != null && hint != null), |
There was a problem hiding this comment.
Nit: Another option is hintText == null || hint == null, either way is fine though.
| /// The widget to use in place of the [hintText]. | ||
| /// Either [hintText] or [hint] can be specified, but not both. |
There was a problem hiding this comment.
You need an empty line of /// in between these two lines.
…tter into hint-widget-161130
<!-- 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 --> Adds a new property to InputDecoration `hintTextWidget` *Fixes*: flutter#161130 With the introduction of ~hintTextWidget~ hint We should be able to animate hintText https://github.com/user-attachments/assets/7955a835-5f60-4451-8ede-b5e5f0457046 https://github.com/user-attachments/assets/55d7f021-cc8f-471e-a1d8-e601262ff640 <details> <summary>sample code</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @OverRide Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @OverRide State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin { String _searchText = 'Popular Picks'; List<String> wordsToShow = [ 'Popular Picks', 'Trending', 'New Arrivals', 'Best Sellers', 'Top Rated', ]; int index = 0; @OverRide Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextField( cursorHeight: 16, decoration: InputDecoration( maintainHintHeight: true, hintTextWidget: Row( children: [ const Text( "Search for ", style: TextStyle(fontSize: 16), ), SlidingText( onCompleted: () { index = (index + 1) % wordsToShow.length; setState(() { _searchText = wordsToShow[index]; }); }, word: _searchText, interval: 1500, isDelay: true), ], ), border: OutlineInputBorder(), ), ), ], ), ), ), ); } } class SlidingText extends StatefulWidget { final String word; final int interval; final bool isDelay; final Function onCompleted; const SlidingText({ required this.word, required this.interval, required this.isDelay, required this.onCompleted, Key? key, }) : super(key: key); @OverRide _SlidingTextState createState() => _SlidingTextState(); } class _SlidingTextState extends State<SlidingText> with SingleTickerProviderStateMixin { late AnimationController _animController; late Animation<Offset> _slideAnimation; late Animation<double> _fadeAnimation; @OverRide void initState() { super.initState(); _animController = AnimationController( duration: Duration(milliseconds: widget.interval), vsync: this, ); _slideAnimation = Tween<Offset>( begin: Offset(0, 0.5), end: Offset(0, -0.6), ).animate( CurvedAnimation( parent: _animController, curve: Curves.easeInOut, ), ); _fadeAnimation = TweenSequence([ TweenSequenceItem( tween: Tween<double>(begin: 0.0, end: 1.0).chain( CurveTween(curve: Curves.easeIn), ), weight: 50, // First half of the animation ), TweenSequenceItem( tween: Tween<double>(begin: 1.0, end: 0.0).chain( CurveTween(curve: Curves.easeOut), ), weight: 50, // Second half of the animation ), ]).animate(_animController); // add interval _animController.addStatusListener((status) async { if (status == AnimationStatus.completed) { await Future.delayed(Duration(milliseconds: 500)); widget.onCompleted(); } }); _animController.forward(); } @OverRide void didUpdateWidget(covariant SlidingText oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.word != widget.word) { _animController.reset(); _animController.forward(); } } @OverRide void dispose() { _animController.dispose(); super.dispose(); } @OverRide Widget build(BuildContext context) { return AnimatedBuilder( animation: _animController, builder: (context, child) { return SlideTransition( position: _slideAnimation, child: FadeTransition( opacity: _fadeAnimation, child: Text( widget.word, style: const TextStyle(fontSize: 16), ), ), ); }, ); } } ``` </details> ## 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
|
Has this reached stable? Not able to find. @maheshj01 |
This isn't currently available on the latest Flutter Stable channel. will probably in the next major release.
|

Adds a new property to InputDecoration
hintTextWidgethintFixes: #161130
With the introduction of
hintTextWidgethint We should be able to pass a custom widget. This will allow creating such animated experiencesScreen.Recording.2025-01-10.at.09.50.49.mov
Screen.Recording.2025-01-10.at.13.41.28.mov
sample code
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.