Last active
September 16, 2021 11:05
-
-
Save fabiancrx/47662fda1495ef2172f53f5b98974f04 to your computer and use it in GitHub Desktop.
Automatically scroll to widget when focus gained in Flutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:ui'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_hooks/flutter_hooks.dart'; | |
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; | |
/// Given a [focusNode] when it gains focus it will scroll to the widget that is wrapped by [ScrollWhenFocusGained] | |
/// Useful for when working with forms in which they keyboard can obscure areas of the screen. | |
/// It also provides a [onFocus] fallback method to be execute if the view could not be scrolled correctly. | |
/// | |
/// Usage | |
///``` | |
/// ScrollWhenFocusGained( | |
/// focusNode: _focusNode, | |
/// child: TextFormField( focusNode: _focusNode,) | |
///``` | |
class ScrollWhenFocusGained extends HookWidget { | |
final VoidCallback? onErrorFocusing; | |
final FocusNode focusNode; | |
final Widget child; | |
final Duration? animationDuration; | |
const ScrollWhenFocusGained({ | |
Key? key, | |
this.animationDuration, | |
this.onErrorFocusing, | |
required this.child, | |
required this.focusNode, | |
}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
late final keyboardVisibilityController = KeyboardVisibilityController(); | |
void _scrollWhenFocusGained([double offset = 40]) { | |
print('Keyboard visibility direct query: ${keyboardVisibilityController.isVisible}'); | |
if (focusNode.hasPrimaryFocus) { | |
try { | |
// Query | |
// Subscribe | |
keyboardVisibilityController.onChange.listen((bool visible) { | |
print('Keyboard visibility update. Is visible: ${visible}'); | |
if (visible) { | |
Future.delayed(const Duration(milliseconds: 200)).then((value) { | |
// focusNode.requestFocus(); | |
Scrollable.ensureVisible( | |
context, | |
alignment: 0.5, | |
curve: Curves.decelerate, | |
duration: animationDuration ?? const Duration(milliseconds: 160), | |
); | |
}); | |
} | |
}); | |
} catch (e) { | |
print('Could not ensure visibility $e'); | |
if (onErrorFocusing != null) onErrorFocusing!(); | |
} | |
} | |
} | |
useEffect(() { | |
focusNode.addListener(_scrollWhenFocusGained); | |
return () => focusNode.removeListener(_scrollWhenFocusGained); | |
}, []); | |
return child; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment