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

Flutter Material项目iOS端底部按钮被系统导航栏遮挡的解决方法

Flutter按钮在iOS被底部导航栏遮挡的解决方案

问题描述

开发了一个Material风格的Flutter应用,底部设置了一个按钮,该按钮在Android端显示正常,但在iOS端会被底部系统导航栏遮挡。

问题截图:
问题截图

当前代码:

Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Expanded(
            flex: 2,
            child: SvgPicture.asset(
              "assets/logo.svg",
              fit: BoxFit.contain,
              width: double.infinity,
            ),
          ),
          Text(initMessage),
          const Spacer(
            flex: 1,
          ),
          ElevatedButton(
              onPressed: () => navigatorKey.currentState?.pushNamed('/help'),
              child: const Text('Show Help'))
        ],
      ),
    );
  }

解决方案

iOS底部存在系统安全区域(Home Indicator区域),默认情况下Scaffold的body不会自动避开该区域,而Android的导航栏处理逻辑不同,因此出现差异。可以通过以下几种方式解决:

方式一:使用SafeArea包裹按钮

SafeArea会自动识别当前平台的安全区域,让按钮避开系统导航栏/状态栏,是最简洁的适配方案。

修改后的代码:

Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Expanded(
          flex: 2,
          child: SvgPicture.asset(
            "assets/logo.svg",
            fit: BoxFit.contain,
            width: double.infinity,
          ),
        ),
        Text(initMessage),
        const Spacer(flex: 1),
        // 用SafeArea包裹按钮,自动适配底部安全区域
        SafeArea(
          child: ElevatedButton(
              onPressed: () => navigatorKey.currentState?.pushNamed('/help'),
              child: const Text('Show Help')),
        )
      ],
    ),
  );
}

方式二:手动添加安全区域内边距

通过MediaQuery获取底部安全区域的高度,给整个内容区域添加底部内边距,确保按钮不被遮挡。

修改后的代码:

Widget build(BuildContext context) {
  // 获取当前设备的底部安全区域高度
  final bottomSafeHeight = MediaQuery.of(context).padding.bottom;

  return Scaffold(
    body: Padding(
      // 给内容添加底部内边距,高度等于安全区域高度
      padding: EdgeInsets.only(bottom: bottomSafeHeight),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Expanded(
            flex: 2,
            child: SvgPicture.asset(
              "assets/logo.svg",
              fit: BoxFit.contain,
              width: double.infinity,
            ),
          ),
          Text(initMessage),
          const Spacer(flex: 1),
          ElevatedButton(
              onPressed: () => navigatorKey.currentState?.pushNamed('/help'),
              child: const Text('Show Help'))
        ],
      ),
    ),
  );
}

方式三:将按钮放在Scaffold的bottomNavigationBar中

如果按钮是固定在底部的操作按钮,可以直接利用Scaffold的bottomNavigationBar属性,该属性会自动处理安全区域适配。

修改后的代码:

Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Expanded(
          flex: 2,
          child: SvgPicture.asset(
            "assets/logo.svg",
            fit: BoxFit.contain,
            width: double.infinity,
          ),
        ),
        Text(initMessage),
        const Spacer(flex: 1),
      ],
    ),
    // 将按钮放在bottomNavigationBar中,自动适配安全区域
    bottomNavigationBar: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      child: ElevatedButton(
          onPressed: () => navigatorKey.currentState?.pushNamed('/help'),
          child: const Text('Show Help')),
    ),
  );
}

方案对比

  • SafeArea:自动适配所有平台安全区域,代码简洁,推荐优先使用。
  • 手动内边距:适合需要自定义内边距或结合其他布局的场景,灵活性更高。
  • bottomNavigationBar:适合按钮作为底部固定操作栏的场景,自带布局适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:55:36