You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中实现键盘弹出时隐藏miniCenterDocked类型FloatingActionButton

解决键盘弹出时miniCenterDocked类型FloatingActionButton的位置问题

针对键盘弹出时FloatingActionButton上浮的问题,提供两种可行方案:


方案一:键盘弹出时隐藏FloatingActionButton

通过监听键盘的显示/隐藏状态,动态控制FAB的显示与否。

修改后的完整代码

import 'package:ecommerce/pages/all_products.dart';
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  int currentTab = 2;
  final List<Widget> screens = [
    const Text('Profile'),
    const Text('Search'),
    const AllProductsPage(),
    const Text('Favorites'),
    const Text('Cart'),
  ];

  final PageStorageBucket bucket = PageStorageBucket();
  Widget currentScreen = const AllProductsPage();
  bool _isKeyboardVisible = false; // 标记键盘是否处于显示状态

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

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

  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
    final bottomInset = WidgetsBinding.instance.window.viewInsets.bottom;
    setState(() {
      _isKeyboardVisible = bottomInset > 0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        extendBody: true,
        body: PageStorage(
          bucket: bucket,
          child: currentScreen,
        ),
        // 根据键盘状态控制FAB显示/隐藏
        floatingActionButton: _isKeyboardVisible
            ? null
            : FloatingActionButton(
                onPressed: () {
                  _updateScreen(2, const AllProductsPage());
                },
                child: Icon(
                  Icons.home,
                  color: _getColor(2),
                ),
              ),
        floatingActionButtonLocation:
            FloatingActionButtonLocation.miniCenterDocked,
        bottomNavigationBar: BottomAppBar(
          shape: const CircularNotchedRectangle(),
          notchMargin: 12,
          child: SizedBox(
            height: 70,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    _createItemBar(Icons.person, 0, 'Profile'),
                    _createItemBar(Icons.search, 1, 'Search'),
                  ],
                ),
                Row(
                  children: [
                    _createItemBar(Icons.favorite, 3, 'Favorites'),
                    _createItemBar(Icons.shopping_cart, 4, 'Cart'),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _createItemBar(IconData icon, int index, String text) {
    return MaterialButton(
      splashColor: Colors.transparent,
      minWidth: 40,
      onPressed: () {
        _updateScreen(index, screens[index]);
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(icon, color: _getColor(index)),
          Text(
            text,
            style: TextStyle(
              color: _getColor(index),
            ),
          ),
        ],
      ),
    );
  }

  Color _getColor(int index) {
    return currentTab == index ? Colors.green : Colors.grey;
  }

  void _updateScreen(int index, Widget screen) {
    setState(() {
      currentScreen = screen;
      currentTab = index;
    });
  }
}

方案二:键盘弹出时固定FloatingActionButton位置

禁止Scaffold随键盘调整布局,同时确保TextField不被键盘遮挡。

步骤1:修改HomePage的Scaffold配置

@override
Widget build(BuildContext context) {
  return SafeArea(
    child: Scaffold(
      extendBody: true,
      resizeToAvoidBottomInset: false, // 禁止Scaffold随键盘调整布局
      body: PageStorage(
        bucket: bucket,
        child: currentScreen,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _updateScreen(2, const AllProductsPage());
        },
        child: Icon(
          Icons.home,
          color: _getColor(2),
        ),
      ),
      floatingActionButtonLocation:
          FloatingActionButtonLocation.miniCenterDocked,
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        notchMargin: 12,
        child: SizedBox(
          height: 70,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Row(
                children: [
                  _createItemBar(Icons.person, 0, 'Profile'),
                  _createItemBar(Icons.search, 1, 'Search'),
                ],
              ),
              Row(
                children: [
                  _createItemBar(Icons.favorite, 3, 'Favorites'),
                  _createItemBar(Icons.shopping_cart, 4, 'Cart'),
                ],
              ),
            ],
          ),
        ),
      ),
    ),
  );
}

步骤2:调整包含TextField的页面(如AllProductsPage)

class AllProductsPage extends StatelessWidget {
  const AllProductsPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Padding(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom,
        ),
        child: Column(
          children: [
            // 页面其他内容
            const TextField(
              decoration: InputDecoration(hintText: "输入搜索内容"),
            ),
            // 页面其他内容
          ],
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者KIRO EMAD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:43:16