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

Flutter实现底部上滑动画Overlay布局问题求助

实现底部滑入的半屏选择Overlay

别用Dialog了,Flutter自带的showModalBottomSheet就是专门做这种底部滑入面板的,完全匹配你的需求。下面直接上可运行的代码示例,关键部分我会标注清楚:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('底部选择面板示例')),
        body: const Center(child: SelectButton()),
      ),
    );
  }
}

class SelectButton extends StatefulWidget {
  const SelectButton({super.key});

  @override
  State<SelectButton> createState() => _SelectButtonState();
}

class _SelectButtonState extends State<SelectButton> {
  String? selectedOption;

  void _showBottomSheet() {
    showModalBottomSheet(
      // 允许自定义高度,突破默认的最大高度限制
      isScrollControlled: true,
      // 设置顶部圆角,优化UI
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      context: context,
      builder: (context) {
        // 限制面板最大高度为屏幕的一半
        return Container(
          constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height / 2,
          ),
          child: ListView(
            padding: const EdgeInsets.symmetric(vertical: 16),
            children: [
              // 选项列表
              _buildOptionItem('选项1'),
              _buildOptionItem('选项2'),
              _buildOptionItem('选项3'),
              _buildOptionItem('选项4'),
              _buildOptionItem('选项5'),
              _buildOptionItem('选项6'),
            ],
          ),
        );
      },
    ).then((value) {
      // 处理选中的选项,更新页面状态
      if (value != null) {
        setState(() {
          selectedOption = value;
        });
      }
    });
  }

  Widget _buildOptionItem(String option) {
    return InkWell(
      onTap: () {
        // 关闭面板并返回选中的选项
        Navigator.pop(context, option);
      },
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
        child: Text(
          option,
          style: const TextStyle(fontSize: 16),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
          onPressed: _showBottomSheet,
          child: const Text('Select'),
        ),
        if (selectedOption != null)
          Padding(
            padding: const EdgeInsets.only(top: 20),
            child: Text('选中的选项: $selectedOption'),
          ),
      ],
    );
  }
}

关键细节说明:

  • isScrollControlled: true:必须设置这个参数,否则面板的高度会被限制在屏幕的约三分之二,无法做到刚好一半高度。
  • maxHeight: MediaQuery.of(context).size.height / 2:通过Container的constraints直接限制面板最大高度为屏幕一半,内容超过高度时会自动滚动。
  • Navigator.pop(context, option):点击选项时关闭面板,同时把选中的值返回给调用方,方便后续处理。
  • shape参数:给面板顶部加圆角,比默认的直角更美观,你可以根据自己的UI需求调整。

这个方案完全满足你的需求:点击按钮后面板从底部滑入,最大占屏幕一半,选项可点击,点击后关闭面板。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 08:43:18