【问题标题】:Detect when widget changes position in Flutter检测小部件何时在 Flutter 中更改位置
【发布时间】:2019-04-20 02:29:38
【问题描述】:

有什么方法可以检测小部件何时改变位置?比如键盘弹起,内容上移的时候?我想在不依赖焦点事件或尝试检测键盘状态的情况下检测到这一点。

这是一个示例应用:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: MyTextField()
        )
      )
    );
  }
}

class MyTextField extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return TextField();
  }

}

MyTextField 被聚焦时,如何检测它何时向上移动?

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    您可以使用WidgetsBindingObserver 来检测指标何时发生变化,这里有一个示例,但您必须使用 GlobalKey 来检查 Widget 的新位置:

        class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
          GlobalKey _key = GlobalKey();
    
          @override
          void initState() {
            WidgetsBinding.instance.addObserver(this);
            super.initState();
          }
    
          @override
          void dispose() {
            WidgetsBinding.instance.removeObserver(this);
            super.dispose();
          }
    
          @override
          void didChangeMetrics() {
            final RenderBox renderBox = _key.currentContext.findRenderObject();
            final position = renderBox.localToGlobal(Offset.zero);
            print("position : ${position.dx},${position.dy}");
          }
    
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              body: Center(
                child: MyTextField(
                  key: _key,
                ),
              ),
            );
          }
        }
    
        class MyTextField extends StatelessWidget {
          const MyTextField({Key key}) : super(key: key);
    
          @override
          Widget build(BuildContext context) {
            return TextField();
          }
        }
    

    【讨论】:

    • 嘿,我认为这是可行的,但我相信在 didChangeMetrics 中打印的位置实际上是 TextField 的旧位置,在它改变位置之前。有没有办法获得新职位?
    • 仅当窗口指标发生变化而不是小部件的位置时才有效
    • @diegoveloper 我收到了A value of type 'RenderObject?' can't be assigned to a variable of type 'RenderBox?'.
    【解决方案2】:

    如果你只是想知道键盘是否可见,你可以使用这个:

    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      @override
      void didChangeMetrics() {
        print('Is the keyboard visible? ${window.viewInsets.bottom != 0 ? 'yes' : 'no'}');
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: TextField(),
            ),
          ),
        );
      }
    }
    

    说明:通过获取绘制应用的矩形的底部位置,可以推断系统组件是否减少了应用的空间,因此键盘是否可见。

    这仅回答了您问题的这一部分:

    比如键盘弹起,内容上移的时候?

    但至少绘制应用程序的矩形的大小始终是当前大小,而不是旧大小。这是@diegoveloper 的答案的问题,你总是得到TextField 的旧位置。

    【讨论】:

      猜你喜欢
      • 2022-06-18
      • 2019-05-01
      • 2023-03-08
      • 2014-12-24
      • 1970-01-01
      • 1970-01-01
      • 2012-12-19
      • 2022-06-30
      • 2018-12-04
      相关资源
      最近更新 更多