-
Notifications
You must be signed in to change notification settings - Fork 350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] [Regression from v4] Suggestions box not resizing after scroll #555
Comments
Any update on this? I am facing this issue still |
Hi @davidmartos96, It's currently unclear to me whether this would be desirable behaviour. In the last version, this behaviour seemed to barely work correctly on desktop platforms. We might run into some issues with how we hide the box when it is out of view. When I wrote version 5, I have intentionally left this out, as it seemed janky and I was unsure whether we actually want it. |
@clragon Thank you for considering! It's how I'm currently using typeahead in a scrollable UI. To improve UX, if the user focuses the field when it's almost at the bottom in the viewport, I scroll the necessary pixels in order to show some amount of the suggestions box. With v5 I cannot manage to make the same behavior. What behavior barely worked on desktop? I'm trying the demo from this comment on both desktop and mobile and it works how I expect. If the box goes out of view it also hides correctly The user would tap the typeahead when the UI is like this: import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TypeAhead Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ScrollExample(),
);
}
}
class ScrollExample extends StatelessWidget {
const ScrollExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scroll Example'),
),
body: Scrollbar(
child: ListView(
primary: true,
children: [
const Center(
child: Text(
'BELOW THERE IS A TYPEAHEAD FIELD.',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
for (int i = 0; i < 10; i++)
Container(
margin: const EdgeInsets.all(8.0),
height: 50,
color: Colors.red.withOpacity(0.3),
child: Center(
child: Text("some UI above field $i"),
),
),
Container(
margin: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8.0),
color: Colors.blue.withOpacity(0.3),
child: const _TypeadFieldWrapper(),
),
for (int i = 0; i < 20; i++)
Container(
margin: const EdgeInsets.all(8.0),
height: 50,
color: Colors.green.withOpacity(0.3),
child: Center(
child: Text("some UI below field $i"),
),
),
],
),
),
);
}
}
class _TypeadFieldWrapper extends StatefulWidget {
const _TypeadFieldWrapper();
@override
State<_TypeadFieldWrapper> createState() => __TypeadFieldWrapperState();
}
class __TypeadFieldWrapperState extends State<_TypeadFieldWrapper> {
final FocusNode _focusNode = FocusNode();
final List<String> items = List.generate(50, (index) => "Item $index");
//late final suggestionsController = SuggestionsController<String>();
@override
void initState() {
super.initState();
_focusNode.addListener(_ensureSuggestionsVisible);
}
@override
void dispose() {
_focusNode.removeListener(_ensureSuggestionsVisible);
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Typeahead v5
/* TypeAheadField<String>(
suggestionsController: suggestionsController,
suggestionsCallback: (String pattern) async {
return items.where((item) => item.toLowerCase().startsWith(pattern.toLowerCase())).toList();
},
itemBuilder: (context, String suggestion) {
return ListTile(
title: Text(suggestion),
);
},
onSelected: (String suggestion) {
print("Suggestion selected");
},
), */
// Typeahead v4
return TypeAheadField<String>(
suggestionsCallback: (String pattern) async {
return items.where((item) => item.toLowerCase().startsWith(pattern.toLowerCase())).toList();
},
suggestionsBoxDecoration: const SuggestionsBoxDecoration(
constraints: BoxConstraints(
maxHeight: 300,
),
),
itemBuilder: (context, String suggestion) {
return ListTile(
title: Text(suggestion),
);
},
textFieldConfiguration: TextFieldConfiguration(
focusNode: _focusNode,
),
onSuggestionSelected: (String suggestion) {
print("Suggestion selected");
},
);
}
Future<void> _ensureSuggestionsVisible() async {
// Wait for keyboard open
await Future<void>.delayed(const Duration(milliseconds: 600));
if (!mounted || !_focusNode.hasFocus) return;
final RenderObject fieldRenderObject = context.findRenderObject()!;
final RenderAbstractViewport viewport = RenderAbstractViewport.of(fieldRenderObject);
final ScrollableState scrollableState = Scrollable.of(context);
final ScrollPosition position = scrollableState.position;
final offsetToRevealField = viewport.getOffsetToReveal(fieldRenderObject, 1.0);
// How much of the suggestions box we want to reveal
const double boxRevealSize = 150;
// Add boxRevealSize to offsetToReveal to account for the amount of the suggestions box
final offsetToRevealBox = offsetToRevealField.offset + boxRevealSize;
if (offsetToRevealBox < 0 || position.pixels >= offsetToRevealBox) {
// The desired amount is already visible
return;
}
// Scroll to reveal the suggestions box
await position.animateTo(
offsetToRevealBox,
duration: const Duration(milliseconds: 100),
curve: Curves.linear,
);
}
}
|
Thank you for the elaborate example. |
@clragon Would exposing a |
It would be nice to determine the position of the control in the screen and accordingly change the position of the suggestions (if at the bottom, show suggestions at the top). |
@davidmartos96 The |
Well it didn't work for me. It is related because when my control is too low on my screen, the suggestions are built under the keyboard, resulting in no suggestion box. When I scroll down, nothing happens because there's no resize. |
Also, just added a periodic timer to resize, if the suggestionbox was drawn shrinked because of the available space at the bottom of the screen, calling resize on the controller doesn't do anything. |
@frederikstonge Yes, it didn't work for me either when I tried it out back when I opened the thread. Otherwise I would have gone with the Timer approach too. |
I see. the |
Any news on the issue? Maybe I could help... This is the only package decent enough to use. |
I'm not sure if this is exactly the same as #455, because that issue appears to exist on v4 unlike this one, but looks somewhat related.
Steps to reproduce
These steps can be run on version v4.8.0 and v5.x to see the difference
Expected results
The suggestions box should be resized automatically according to its constraints after the scroll action has finished.
This was the behavior in version v4.
The original code from v4 which was taking care of this has been removed. https://github.com/AbdulRahmanAlHamali/flutter_typeahead/blob/c6ff9b23581a072b3208ec99d6040971b39db848/lib/src/material/field/typeahead_field.dart#L612C31-L612C31
Actual results
The box does not resize
Package Version
5.0.1
Platform
Android
Code sample
The text was updated successfully, but these errors were encountered: