Flutter底部弹出菜单插件over_bottom_sheet的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter底部弹出菜单插件over_bottom_sheet的使用

OverBottomSheet

OverBottomSheet 是一个始终显示底部弹出菜单的 Widget。它允许用户通过手势或按钮控制菜单的展开和关闭。


使用方法

以下是 OverBottomSheet 的使用示例:

import 'package:flutter/material.dart';
import 'package:over_bottom_sheet/over_bottom_sheet.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'OverBottomSheet Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: Colors.blue,
        brightness: Brightness.light,
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: Colors.blue,
        brightness: Brightness.dark,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 创建控制器用于管理弹出菜单的状态
  final _controller = OverBottomSheetController();

  @override
  void dispose() {
    // 释放控制器资源
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('OverBottomSheet 示例'),
      ),
      body: OverBottomSheet(
        // 设置剪裁行为
        clipBehavior: Clip.hardEdge,
        // 设置底部菜单的圆角样式
        shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(32),
            topRight: Radius.circular(32),
          ),
        ),
        // 设置底部菜单的最大高度、最小高度和最大宽度
        sizeOption: const OverBottomSheetSizeOption.mix(
          maxHeight: 0.8, // 最大高度为屏幕高度的80%
          minHeight: 120,  // 最小高度为120像素
          maxWidth: 0.8,   // 最大宽度为屏幕宽度的80%
        ),
        // 控制器实例
        controller: _controller,
        // 自定义头部区域
        headerBuilder: (context, ratio) => Center(
          child: Padding(
            padding: const EdgeInsets.all(8),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                // 动态更新按钮图标
                ValueListenableBuilder<double>(
                  valueListenable: _controller,
                  builder: (context, value, child) => IconButton(
                    onPressed: () {
                      if (value <= 0.5) {
                        _controller.open(); // 打开菜单
                      } else {
                        _controller.close(); // 关闭菜单
                      }
                    },
                    icon: value >= 0.5
                        ? const Icon(Icons.expand_more) // 收缩状态
                        : const Icon(Icons.expand_less), // 展开状态
                  ),
                ),
                // 显示当前菜单展开比例
                Text('ratio: ${ratio.toStringAsFixed(3)}'),
              ],
            ),
          ),
        ),
        // 自定义菜单内容
        content: ListView.builder(
          itemCount: 20, // 示例列表项数量
          itemBuilder: (context, index) => ListTile(
            title: Text('sheet $index'), // 每个列表项显示 "sheet X"
          ),
        ),
        // 主页面内容
        child: Container(
          color: Colors.indigo,
          child: ListView.builder(
            itemCount: 20,
            itemBuilder: (context, index) => ListTile(
              title: Text('main $index'), // 每个列表项显示 "main X"
            ),
          ),
        ),
      ),
    );
  }
}

示例代码解释

1. 导入依赖

确保在项目中已安装 over_bottom_sheet 插件,并正确导入。

2. 创建控制器

OverBottomSheetController 是用于控制底部弹出菜单打开和关闭的核心类。每次使用时需要创建一个新的实例。

final _controller = OverBottomSheetController();

3. 配置弹出菜单

通过 OverBottomSheet 的参数配置菜单的外观和行为:

  • clipBehavior: 剪裁行为,这里设置为 Clip.hardEdge
  • shape: 设置圆角样式。
  • sizeOption: 定义菜单的高度和宽度范围。
  • controller: 绑定控制器以管理菜单状态。
  • headerBuilder: 自定义顶部区域。
  • content: 定义菜单的内容。

4. 动态头部

通过 ValueListenableBuilder 实现动态更新头部按钮的图标和文字,根据当前菜单展开的比例动态调整。

ValueListenableBuilder<double>(
  valueListenable: _controller,
  builder: (context, value, child) => IconButton(
    onPressed: () {
      if (value <= 0.5) {
        _controller.open();
      } else {
        _controller.close();
      }
    },
    icon: value >= 0.5
        ? const Icon(Icons.expand_more)
        : const Icon(Icons.expand_less),
  ),
)

5. 菜单内容

使用 ListView.builder 构建动态内容区域,例如一个包含多个列表项的菜单。

content: ListView.builder(
  itemCount: 20,
  itemBuilder: (context, index) => ListTile(
    title: Text('sheet $index'),
  ),
),

更多关于Flutter底部弹出菜单插件over_bottom_sheet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter底部弹出菜单插件over_bottom_sheet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


over_bottom_sheet 是一个 Flutter 插件,用于在屏幕底部显示一个模态的底部菜单。它类似于 Flutter 自带的 showModalBottomSheet,但提供了更多的自定义选项和灵活性。

安装

首先,你需要在 pubspec.yaml 文件中添加 over_bottom_sheet 依赖:

dependencies:
  flutter:
    sdk: flutter
  over_bottom_sheet: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

基本用法

以下是一个简单的示例,展示如何使用 over_bottom_sheet 来显示一个底部菜单:

import 'package:flutter/material.dart';
import 'package:over_bottom_sheet/over_bottom_sheet.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('OverBottomSheet Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              OverBottomSheet.show(
                context,
                builder: (context) {
                  return Container(
                    height: 200,
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
                    ),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text('This is a bottom sheet'),
                        SizedBox(height: 20),
                        ElevatedButton(
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                          child: Text('Close'),
                        ),
                      ],
                    ),
                  );
                },
              );
            },
            child: Text('Show Bottom Sheet'),
          ),
        ),
      ),
    );
  }
}

参数说明

OverBottomSheet.show 方法接受以下参数:

  • context: BuildContext,用于显示底部菜单。
  • builder: 一个返回 Widget 的函数,用于构建底部菜单的内容。
  • backgroundColor: 底部菜单的背景颜色。
  • elevation: 底部菜单的阴影高度。
  • shape: 底部菜单的形状,例如圆角。
  • isDismissible: 是否可以通过点击外部关闭底部菜单。
  • enableDrag: 是否可以通过拖动关闭底部菜单。
  • barrierColor: 底部菜单背后的遮罩颜色。

自定义示例

以下是一个更复杂的示例,展示了如何使用 over_bottom_sheet 的自定义选项:

OverBottomSheet.show(
  context,
  builder: (context) {
    return Container(
      height: 300,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      child: Column(
        children: [
          Container(
            height: 50,
            decoration: BoxDecoration(
              color: Colors.blue,
              borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
            ),
            child: Center(
              child: Text(
                'Custom Bottom Sheet',
                style: TextStyle(color: Colors.white, fontSize: 18),
              ),
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: 10,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text('Item $index'),
                );
              },
            ),
          ),
        ],
      ),
    );
  },
  backgroundColor: Colors.transparent,
  elevation: 10,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
  ),
  isDismissible: true,
  enableDrag: true,
  barrierColor: Colors.black54,
);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!