程序员@IT·互联网

Flutter 中监听键盘弹出&键盘高度

2025-04-29  本文已影响0人  黑炭长

在移动端的开发中,监听键盘弹起 & 键盘高度是比较常用的功能,特别是聊天页面,那么如何优雅的弹出输入框呢,这里需要分情况处理

1、输入框在页面底部的(经典的聊天窗口)

这种情况相对简单一些直接使用Scaffold自带的弹出键盘的效果 会自动的将输入框的视图置于键盘顶部,我们无需过多处理

Scaffold(
  body:Column(
    children: [
       Expanded(
          child:ListView.builder(
            itemBuilder: (ctx, i) {
               return Container();
            }
          ),
       ),
       SafeArea(
          top: false,
          child: textInputContainer(),
       ),
     ],
  ),
)

类似上述的结构 点击输入框textInputContainer 系统自动处理

2、我们说特殊情况的输入框

我们这边有一个需求 输入框 不在底部 距离底部120的地方,这个时候 还是用1中的方法,会发现 输入框底部始终有一个120的高度,这就要说一下Scaffold 自动弹起键盘的机制了,实际上是 将整个视图高度缩短了一个键盘的高度,这种情况显然就不能满足我们的需求了,我们应该怎么处理 直接上代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '键盘适应示例',
      home: KeyboardAwarePage(),
    );
  }
}

class KeyboardAwarePage extends StatefulWidget {
  @override
  _KeyboardAwarePageState createState() => _KeyboardAwarePageState();
}

class _KeyboardAwarePageState extends State<KeyboardAwarePage> with WidgetsBindingObserver {
  double _keyboardHeight = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this); // 监听窗口变化
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    final bottomInset = WidgetsBinding.instance.window.viewInsets.bottom;
    setState(() {
      _keyboardHeight = bottomInset / MediaQuery.of(context).devicePixelRatio;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('键盘监听示例')),
      resizeToAvoidBottomInset: false,
      body: Stack(
        children: [
          // 主体内容
          Positioned.fill(
            child: Center(child: Text("主内容区域")),
          ),

          // 输入框
          Positioned(
            left: 0,
            right: 0,
            bottom: _keyboardHeight > 0 ? _keyboardHeight : 80,
            child: Container(
              color: Colors.white,
              padding: EdgeInsets.all(12),
              child: TextField(
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: "请输入内容",
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

设置 resizeToAvoidBottomInset: false 不使用Scaffold的该功能 自己维度底部偏移

3,键盘的监听

FocusNode inputFocus = FocusNode();
/// 监听键盘
inputFocus.addListener(() {
  hasFocus.value = inputFocus.hasFocus;
});
TextField(
  scrollPadding: EdgeInsets.zero,
  focusNode: controller.inputFocus,
)
上一篇 下一篇

猜你喜欢

热点阅读