Flutter底部收缩布局插件shrink_sheet_layout的使用

简介

shrink_sheet_layout 是一个用于实现可拖动底部弹出框的 Flutter 插件。其功能类似于 YouTube 应用中的底部弹出框效果。该插件允许用户轻松地在应用中添加一个可拖动的底部弹出界面,并且支持自定义动画效果。

特性

  • 支持创建可拖动的底部弹出框。
  • 提供丰富的配置选项来调整弹出框的行为和外观。
  • 默认提供了多种动画效果,如展开和收缩。

注意:目前尚不支持自动显示和隐藏弹出框的功能。

使用步骤

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 shrink_sheet_layout 依赖:

dependencies:
  shrink_sheet_layout: ^版本号

然后运行以下命令安装依赖:

dart pub get

2. 导入包并在项目中使用

在你的 main.dart 文件中导入 shrink_sheet_layout 并将其集成到应用中:

import 'dart:developer';

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

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const Scaffold(
        body: SafeArea(
          child: MyHomePage(),
        ),
      ),
    );
  }
}

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

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  late final ShrinkSheetController controller1;
  late final ShrinkSheetController controller2;

  [@override](/user/override)
  void initState() {
    super.initState();
    // 初始化控制器,设置动画参数
    controller1 = ShrinkSheetController.simple(
      vsync: this,
      shrinkDuration: const Duration(milliseconds: 1000), // 收缩动画时长
      fadeInDuration: const Duration(milliseconds: 1000), // 淡入动画时长
    );
    controller2 = ShrinkSheetController.simple(
      vsync: this,
      shrinkDuration: const Duration(milliseconds: 500),
      fadeInDuration: const Duration(milliseconds: 500),
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: ShrinkSheetLayout(
        animation: controller1, // 第一层弹出框控制器
        shrinkHeight: 60, // 弹出框的最小高度
        shrinkPadding: const EdgeInsets.only(bottom: 60), // 弹出框的最小内边距
        backdropColor: Theme.of(context).colorScheme.background, // 背景颜色
        backdropMaxOpacity: 1, // 背景最大透明度
        backdropOpacityFactor: 0.5, // 背景透明度因子
        contentBuilder: ShrinkSheetContentBuilder.simple(
          thumbSizeCalculator: ThumbSizeCalculator.fit(MediaQuery.of(context).size.width / 16 * 9), // 自适应比例计算
          thumb: ShrinkSheetThumb(
            child: Container(
              color: Colors.grey[800], // 拖动手柄的颜色
              child: Center(
                child: Text(
                  "VIDEO AREA", // 手柄上的文字
                  style: Theme.of(context).textTheme.bodyMedium!.copyWith(
                        color: Theme.of(context).colorScheme.background,
                      ),
                ),
              ),
            ),
          ),
          content: ShrinkSheetLayout(
            animation: controller2, // 第二层弹出框控制器
            shrinkHeight: 60, // 第二层弹出框的最小高度
            expandPadding: const EdgeInsets.only(top: 2), // 展开时的内边距
            shrinkPadding: const EdgeInsets.all(8), // 收缩时的内边距
            paddingDodgeSheet: 120, // 避免遮挡的区域
            minPaddingDodgeSheet: 60, // 最小避免遮挡的区域
            contentBuilder: ShrinkSheetContentBuilder.simple(
              thumbSizeCalculator: ThumbSizeCalculator.fit(60), // 手柄大小固定为 60
              thumb: ShrinkSheetThumb(
                child: Container(
                  color: Colors.grey, // 手柄背景色
                  child: Center(
                    child: TextButton(
                      onPressed: controller2.fadeOut, // 点击按钮淡出弹出框
                      child: Text("点击此处淡出弹出框"), // 按钮文本
                    ),
                  ),
                ),
              ),
              content: Container(
                color: Colors.amber, // 弹出框内容背景色
                child: const Center(child: Text("文本")), // 弹出框内容
              ),
            ),
            body: TextButton(
              onPressed: () {
                log("测试日志"); // 日志记录
                controller1.shrink(); // 收缩第一层弹出框
                controller2.expand(); // 展开第二层弹出框
              },
              child: const Text("主体"), // 主体按钮文本
            ),
          ),
        ),
        body: TextButton(
          onPressed: () {
            log("测试日志");
            controller1.expand(); // 展开第一层弹出框
            controller2.fadeIn(); // 淡入第二层弹出框
          },
          child: const Text("主体"), // 主体按钮文本
        ),
      ),
    );
  }
}

更多关于Flutter底部收缩布局插件shrink_sheet_layout的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter底部收缩布局插件shrink_sheet_layout的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


shrink_sheet_layout 是一个 Flutter 插件,用于创建底部可收缩的布局,类似于 Google Maps 或 Apple Maps 中的底部面板。这个插件可以帮助你实现一个可以上下拖动的底部面板,用户可以通过手势来展开或收缩面板。

安装插件

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

dependencies:
  flutter:
    sdk: flutter
  shrink_sheet_layout: ^0.0.1  # 请检查最新版本

然后运行 flutter pub get 来安装插件。

使用 ShrinkSheetLayout

ShrinkSheetLayout 是一个可以包裹在 Scaffold 中的小部件,它允许你定义一个底部面板,并且可以通过手势来展开或收缩。

以下是一个简单的示例,展示了如何使用 ShrinkSheetLayout

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Shrink Sheet Layout Example'),
      ),
      body: ShrinkSheetLayout(
        sheet: Container(
          color: Colors.blue,
          child: Column(
            children: [
              Container(
                height: 50,
                color: Colors.blueGrey,
                child: Center(
                  child: Text('Drag to expand or collapse'),
                ),
              ),
              Expanded(
                child: ListView.builder(
                  itemCount: 20,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text('Item $index'),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
        child: Center(
          child: Text('Main Content'),
        ),
      ),
    );
  }
}
回到顶部