Flutter滑动底部面板插件wtf_sliding_sheet的使用

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

Flutter滑动底部面板插件wtf_sliding_sheet的使用

简介

wtf_sliding_sheet 是一个Flutter插件,允许创建可以拖动和滚动的底部面板,并且可以固定到一系列预定义的高度。它由What the Flutter团队开发并维护。

Sliding Sheet

GitHub仓库 | Pub.dev页面

安装

在您的pubspec.yaml文件中添加依赖:

dependencies:
  wtf_sliding_sheet: ^1.1.0

然后运行以下命令来安装包:

flutter pub get

如果您喜欢这个包,请考虑在GitHub上给它一个星标,在pub.dev上点赞。

使用方法

作为Widget使用

您可以将SlidingSheet作为一个永久显示的组件嵌入到widget树中。

@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.grey.shade200,
    appBar: AppBar(
      title: Text('Simple Example'),
    ),
    body: SlidingSheet(
      elevation: 8,
      cornerRadius: 16,
      snapSpec: const SnapSpec(
        snap: true,
        snappings: [0.4, 0.7, 1.0],
        positioning: SnapPositioning.relativeToAvailableSpace,
      ),
      body: Center(
        child: Text('This widget is below the SlidingSheet'),
      ),
      builder: (context, state) {
        return Container(
          height: 500,
          child: Center(
            child: Text('This is the content of the sheet'),
          ),
        );
      },
    ),
  );
}

结果: Example

作为BottomSheetDialog使用

您也可以通过调用showSlidingBottomSheet函数以对话框的形式展示SlidingSheet

void showAsBottomSheet(BuildContext context) async {
  final result = await showSlidingBottomSheet(
    context,
    builder: (context) {
      return SlidingSheetDialog(
        elevation: 8,
        cornerRadius: 16,
        snapSpec: const SnapSpec(
          snap: true,
          snappings: [0.4, 0.7, 1.0],
          positioning: SnapPositioning.relativeToAvailableSpace,
        ),
        builder: (context, state) {
          return Container(
            height: 400,
            child: Center(
              child: Material(
                child: InkWell(
                  onTap: () => Navigator.pop(context, 'This is the result.'),
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: Text(
                      'This is the content of the sheet',
                      style: Theme.of(context).textTheme.bodyMedium,
                    ),
                  ),
                ),
              ),
            ),
          );
        },
      );
    }
  );

  print(result); // This is the result.
}

结果: Example

Snapping配置

SnapSpec用于控制SlidingSheet的停靠行为。

参数 描述
snap 如果为true,则SlidingSheet会根据提供的snappings进行停靠。如果为false,则SlidingSheet将在minExtent和maxExtent之间滑动,然后开始滚动(如果内容高度超过可用空间)。
snappings 当用户结束拖动交互时,SlidingSheet将停靠到这些位置。最小值和最大值代表了SlidingSheet滑动的边界。
positioning 可以设置为三种模式之一:
- SnapPositioning.relativeToAvailableSpace: 相对于总可用高度。
- SnapPositioning.relativeToSheetHeight: 相对于sheet的总高度。
- SnapPositioning.pixelOffset: 固定像素偏移。
onSnap SlidingSheet停靠到某个位置时触发的回调函数。

SheetController

SheetController提供了手动控制SlidingSheet状态的方法。

方法 描述
expand() 展开SlidingSheet至最大高度。
collapse() 收缩SlidingSheet至最小高度。
snapToExtent() SlidingSheet停靠到指定的高度。
scrollTo() 滚动SlidingSheet到指定的偏移量。
rebuild() 重新构建SlidingSheet的所有子部件。
show() 显示隐藏的SlidingSheet
hide() 隐藏SlidingSheet

Headers and Footers

头部和尾部是SlidingSheet的UI元素,它们不会随内容滚动。

SlidingSheet(
  headerBuilder: (context, state) {
    return Container(
      height: 56,
      width: double.infinity,
      color: Colors.green,
      alignment: Alignment.center,
      child: Text(
        'This is the header',
        style: Theme.of(context).textTheme.bodyMedium.copyWith(color: Colors.white),
      ),
    );
  },
  footerBuilder: (context, state) {
    return Container(
      height: 56,
      width: double.infinity,
      color: Colors.yellow,
      alignment: Alignment.center,
      child: Text(
        'This is the footer',
        style: Theme.of(context).textTheme.bodyMedium.copyWith(color: Colors.black),
      ),
    );
  },
)

Material Effects

通过监听SlidingSheet的状态变化,可以实现Material Design风格的效果。

return SheetListenerBuilder(
  buildWhen: (oldState, newState) =>
    oldState.progress != newState.progress,
  builder: (context, SheetState state) {
    return Material(
      elevation: state.progress * 20 + 1,
      color: Colors.lightBlue,
      borderRadius: BorderRadius.vertical(
        top: Radius.circular(16),
      ),
      child: SizedBox(
        height: 60,
        child: Center(
          child: const Text('Header'),
        ),
      ),
    );
  },
);

示例代码

以下是完整的示例代码,展示了如何使用wtf_sliding_sheet插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'wtf_sliding_sheet demo',
      home: Example(),
    );
  }
}

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  SheetController controller = SheetController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Sliding Sheet Example')),
      body: Column(
        children: [
          Expanded(
            child: buildSheet(),
          ),
        ],
      ),
    );
  }

  Widget buildSheet() {
    return SlidingSheet(
      openDuration: Duration(milliseconds: 900),
      controller: controller,
      color: Colors.white,
      shadowColor: Colors.black26,
      elevation: 12,
      maxWidth: 500,
      cornerRadius: 16,
      cornerRadiusOnFullscreen: 0.0,
      closeOnBackdropTap: true,
      closeOnBackButtonPressed: true,
      addTopViewPaddingOnFullscreen: true,
      isBackdropInteractable: true,
      border: Border.all(
        color: Colors.grey.shade300,
        width: 3,
      ),
      snapSpec: const SnapSpec(
        snap: true,
        positioning: SnapPositioning.relativeToAvailableSpace,
        snappings: [
          SnapSpec.headerFooterSnap,
          0.6,
          SnapSpec.expanded,
        ],
      ),
      parallaxSpec: const ParallaxSpec(
        enabled: true,
        amount: 0.35,
        endExtent: 0.6,
      ),
      liftOnScrollHeaderElevation: 12.0,
      liftOnScrollFooterElevation: 12.0,
      body: Center(child: Text('This widget is below the SlidingSheet')),
      headerBuilder: buildHeader,
      footerBuilder: buildFooter,
      builder: buildChild,
    );
  }

  Widget buildHeader(BuildContext context, SheetState state) {
    return Container(
      height: 56,
      width: double.infinity,
      color: Colors.green,
      alignment: Alignment.center,
      child: Text(
        'This is the header',
        style: Theme.of(context).textTheme.bodyMedium.copyWith(color: Colors.white),
      ),
    );
  }

  Widget buildFooter(BuildContext context, SheetState state) {
    return Container(
      height: 56,
      width: double.infinity,
      color: Colors.yellow,
      alignment: Alignment.center,
      child: Text(
        'This is the footer',
        style: Theme.of(context).textTheme.bodyMedium.copyWith(color: Colors.black),
      ),
    );
  }

  Widget buildChild(BuildContext context, SheetState state) {
    return Container(
      height: 500,
      child: Center(
        child: Text('This is the content of the sheet'),
      ),
    );
  }
}

通过上述代码,您可以轻松地在项目中集成wtf_sliding_sheet插件,创建出美观且功能丰富的滑动底部面板。


更多关于Flutter滑动底部面板插件wtf_sliding_sheet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter滑动底部面板插件wtf_sliding_sheet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter中的wtf_sliding_sheet插件来实现滑动底部面板的示例代码。wtf_sliding_sheet是一个强大的插件,用于在Flutter应用中创建可拖动的底部面板。

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

dependencies:
  flutter:
    sdk: flutter
  wtf_sliding_sheet: ^最新版本号 # 请替换为实际的最新版本号

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

接下来是一个完整的示例代码,展示了如何使用wtf_sliding_sheet来创建一个简单的底部滑动面板:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WTF Sliding Sheet Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final SlidingSheetController _controller = SlidingSheetController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WTF Sliding Sheet Demo'),
      ),
      body: Stack(
        children: [
          // 主内容
          Center(
            child: Text(
              'Main Content',
              style: TextStyle(fontSize: 24),
            ),
          ),
          // 滑动底部面板
          SlidingSheet(
            controller: _controller,
            minHeight: 50,
            maxHeight: MediaQuery.of(context).size.height * 0.7,
            builder: (BuildContext context, SlidingSheetState state) {
              return Container(
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(20),
                    topRight: Radius.circular(20),
                  ),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Sliding Sheet Content',
                        style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                      ),
                      SizedBox(height: 16),
                      Text(
                        'This is a sliding bottom sheet panel. You can drag it up and down.',
                        style: TextStyle(fontSize: 16),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 展开或收起面板
          if (_controller.state.isCollapsed) {
            _controller.expand();
          } else {
            _controller.collapse();
          }
        },
        tooltip: 'Toggle Sheet',
        child: Icon(Icons.expand_more),
      ),
    );
  }
}

代码解释

  1. 依赖添加

    • pubspec.yaml中添加wtf_sliding_sheet依赖。
  2. 主应用

    • MyApp是应用的入口,它包含一个MaterialApp和一个MyHomePage
  3. 主页面

    • MyHomePage是一个有状态的小部件,包含一个SlidingSheetController实例来控制底部面板的状态。
  4. 滑动底部面板

    • 使用SlidingSheet小部件创建底部面板,并设置最小高度和最大高度。
    • builder参数用于构建面板内容。
  5. 浮动操作按钮

    • 一个FloatingActionButton用于展开或收起底部面板。

这个示例展示了如何使用wtf_sliding_sheet插件创建一个可拖动的底部面板,并且可以通过按钮控制其展开和收起状态。你可以根据需要进一步自定义面板的内容和样式。

回到顶部