fix: regression selected options not scrolling automatically (#5058)

This commit is contained in:
Richard Shiue 2024-04-10 15:28:26 +08:00 committed by GitHub
parent 11ed32cf4f
commit a1a7321f4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 1 deletions

View File

@ -33,7 +33,8 @@ class SelectOptionCellEditor extends StatefulWidget {
} }
class _SelectOptionCellEditorState extends State<SelectOptionCellEditor> { class _SelectOptionCellEditorState extends State<SelectOptionCellEditor> {
final TextEditingController textEditingController = TextEditingController(); final textEditingController = TextEditingController();
final scrollController = ScrollController();
final popoverMutex = PopoverMutex(); final popoverMutex = PopoverMutex();
late final bloc = SelectOptionCellEditorBloc( late final bloc = SelectOptionCellEditorBloc(
cellController: widget.cellController, cellController: widget.cellController,
@ -86,6 +87,7 @@ class _SelectOptionCellEditorState extends State<SelectOptionCellEditor> {
void dispose() { void dispose() {
popoverMutex.dispose(); popoverMutex.dispose();
textEditingController.dispose(); textEditingController.dispose();
scrollController.dispose();
bloc.close(); bloc.close();
focusNode.dispose(); focusNode.dispose();
super.dispose(); super.dispose();
@ -101,6 +103,7 @@ class _SelectOptionCellEditorState extends State<SelectOptionCellEditor> {
children: [ children: [
_TextField( _TextField(
textEditingController: textEditingController, textEditingController: textEditingController,
scrollController: scrollController,
focusNode: focusNode, focusNode: focusNode,
popoverMutex: popoverMutex, popoverMutex: popoverMutex,
), ),
@ -209,11 +212,13 @@ class _OptionList extends StatelessWidget {
class _TextField extends StatelessWidget { class _TextField extends StatelessWidget {
const _TextField({ const _TextField({
required this.textEditingController, required this.textEditingController,
required this.scrollController,
required this.focusNode, required this.focusNode,
required this.popoverMutex, required this.popoverMutex,
}); });
final TextEditingController textEditingController; final TextEditingController textEditingController;
final ScrollController scrollController;
final FocusNode focusNode; final FocusNode focusNode;
final PopoverMutex popoverMutex; final PopoverMutex popoverMutex;
@ -237,6 +242,7 @@ class _TextField extends StatelessWidget {
selectedOptionMap: optionMap, selectedOptionMap: optionMap,
distanceToText: _editorPanelWidth * 0.7, distanceToText: _editorPanelWidth * 0.7,
textController: textEditingController, textController: textEditingController,
scrollController: scrollController,
textSeparators: const [','], textSeparators: const [','],
onClick: () => popoverMutex.close(), onClick: () => popoverMutex.close(),
newText: (text) { newText: (text) {

View File

@ -20,6 +20,7 @@ class SelectOptionTextField extends StatefulWidget {
required this.newText, required this.newText,
required this.onPaste, required this.onPaste,
required this.onRemove, required this.onRemove,
this.scrollController,
this.onClick, this.onClick,
}); });
@ -28,6 +29,7 @@ class SelectOptionTextField extends StatefulWidget {
final double distanceToText; final double distanceToText;
final List<String> textSeparators; final List<String> textSeparators;
final TextEditingController textController; final TextEditingController textController;
final ScrollController? scrollController;
final FocusNode focusNode; final FocusNode focusNode;
final Function() onSubmitted; final Function() onSubmitted;
@ -46,10 +48,21 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
widget.focusNode.requestFocus(); widget.focusNode.requestFocus();
_scrollToEnd();
}); });
widget.textController.addListener(_onChanged); widget.textController.addListener(_onChanged);
} }
@override
void didUpdateWidget(covariant oldWidget) {
if (oldWidget.selectedOptionMap.length < widget.selectedOptionMap.length) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToEnd();
});
}
super.didUpdateWidget(oldWidget);
}
@override @override
void dispose() { void dispose() {
widget.textController.removeListener(_onChanged); widget.textController.removeListener(_onChanged);
@ -80,6 +93,16 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
); );
} }
void _scrollToEnd() {
if (widget.scrollController?.hasClients ?? false) {
widget.scrollController?.animateTo(
widget.scrollController!.position.maxScrollExtent,
duration: const Duration(milliseconds: 150),
curve: Curves.easeOut,
);
}
}
void _onChanged() { void _onChanged() {
if (!widget.textController.value.composing.isCollapsed) { if (!widget.textController.value.composing.isCollapsed) {
return; return;
@ -132,6 +155,7 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
), ),
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
controller: widget.scrollController,
child: Wrap(spacing: 4, children: children), child: Wrap(spacing: 4, children: children),
), ),
), ),