以下代码是在网上看到的,忘记具体的出处了,请谅解
/**
* 作者:Created by H on 2019/1/23 11:08.
* 介绍: 解决输入框被遮挡问题
*/
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
///
/// Helper class that ensures a Widget is visible when it has the focus
/// For example, for a TextFormField when the keyboard is displayed
///
/// How to use it:
///
/// In the class that implements the Form,
/// Instantiate a FocusNode
/// FocusNode _focusNode = new FocusNode();
///
/// In the build(BuildContext context), wrap the TextFormField as follows:
///
/// new EnsureVisibleWhenFocused(
/// focusNode: _focusNode,
/// child: new TextFormField(
/// ...
/// focusNode: _focusNode,
/// ),
/// ),
///
/// Initial source code written by Collin Jackson.
/// Extended (see highlighting) to cover the case when the keyboard is dismissed and the
/// user clicks the TextFormField/TextField which still has the focus.
///
class EnsureVisibleWhenFocused extends StatefulWidget {
const EnsureVisibleWhenFocused({
Key key,
@required this.child,
@required this.focusNode,
this.curve: Curves.ease,
this.duration: const Duration(milliseconds: 100),
}) : super(key: key);
/// The node we will monitor to determine if the child is focused
final FocusNode focusNode;
/// The child widget that we are wrapping
final Widget child;
/// The curve we will use to scroll ourselves into view.
///
/// Defaults to Curves.ease.
final Curve curve;
/// The duration we will use to scroll ourselves into view
///
/// Defaults to 100 milliseconds.
final Duration duration;
@override
_EnsureVisibleWhenFocusedState createState() => new _EnsureVisibleWhenFocusedState();
}
///
/// We implement the WidgetsBindingObserver to be notified of any change to the window metrics
///
class _EnsureVisibleWhenFocusedState extends State<EnsureVisibleWhenFocused> with WidgetsBindingObserver {
@override
void initState(){
super.initState();
widget.focusNode.addListener(_ensureVisible);
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose(){
WidgetsBinding.instance.removeObserver(this);
widget.focusNode.removeListener(_ensureVisible);
super.dispose();
}
///
/// This routine is invoked when the window metrics have changed.
/// This happens when the keyboard is open or dismissed, among others.
/// It is the opportunity to check if the field has the focus
/// and to ensure it is fully visible in the viewport when
/// the keyboard is displayed
///
@override
void didChangeMetrics(){
if (widget.focusNode.hasFocus){
_ensureVisible();
}
}
///
/// This routine waits for the keyboard to come into view.
/// In order to prevent some issues if the Widget is dismissed in the
/// middle of the loop, we need to check the "mounted" property
///
/// This method was suggested by Peter Yuen (see discussion).
///
Future<Null> _keyboardToggled() async {
if (mounted){
EdgeInsets edgeInsets = MediaQuery.of(context).viewInsets;
while (mounted && MediaQuery.of(context).viewInsets == edgeInsets) {
await new Future.delayed(const Duration(milliseconds: 10));
}
}
return;
}
Future<Null> _ensureVisible() async {
// Wait for the keyboard to come into view
await Future.any([new Future.delayed(const Duration(milliseconds: 300)), _keyboardToggled()]);
// No need to go any further if the node has not the focus
if (!widget.focusNode.hasFocus){
return;
}
// Find the object which has the focus
final RenderObject object = context.findRenderObject();
final RenderAbstractViewport viewport = RenderAbstractViewport.of(object);
assert(viewport != null);
// Get the Scrollable state (in order to retrieve its offset)
ScrollableState scrollableState = Scrollable.of(context);
assert(scrollableState != null);
// Get its offset
ScrollPosition position = scrollableState.position;
double alignment;
if (position.pixels > viewport.getOffsetToReveal(object, 0.0).offset) {
// Move down to the top of the viewport
alignment = 0.0;
} else if (position.pixels < viewport.getOffsetToReveal(object, 1.0).offset){
// Move up to the bottom of the viewport
alignment = 1.0;
} else {
// No scrolling is necessary to reveal the child
return;
}
position.ensureVisible(
object,
alignment: alignment,
duration: widget.duration,
curve: widget.curve,
);
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
引用方式如下:
FocusNode _focusNode = new FocusNode();
new EnsureVisibleWhenFocused(
focusNode: _focusNode,
child: new TextFormField(
...
focusNode: _focusNode,
),
),