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

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

sliding_sheet_new 是一个可以拖动和滚动的 Flutter 小部件,并且可以自动吸附到一组指定的高度。它非常适合用于实现滑动底部面板。

安装

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

dependencies:
  sliding_sheet_new: ^最新版本号

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

flutter packages get

如果喜欢这个插件,请考虑给它一个星,支持一下!

使用

作为永久(或持久)小部件

这种方法通常用于在其他小部件上方永久显示滑动面板。

@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.grey.shade200,
    appBar: AppBar(
      title: Text('简单示例'),
    ),
    body: SlidingSheet(
      elevation: 8,
      cornerRadius: 16,
      snapSpec: const SnapSpec(
        // 启用吸附功能,默认为true。
        snap: true,
        // 设置自定义吸附点。
        snappings: [0.4, 0.7, 1.0],
        // 定义吸附点相对于什么定位。
        positioning: SnapPositioning.relativeToAvailableSpace,
      ),
      // 背景小部件将显示在滑动面板下方,并且可以应用视差效果。
      body: Center(
        child: Text('此小部件位于滑动面板下方'),
      ),
      builder: (context, state) {
        // 这是滑动面板的内容,如果内容比面板可用高度大,则会滚动。
        return Container(
          height: 500,
          child: Center(
            child: Text('这是面板的内容'),
          ),
        );
      },
    ),
  );
}

结果:

Example

作为底部弹出面板

这种方法可以将滑动面板作为底部弹出面板显示,通过调用 showSlidingBottomSheet 函数并返回一个 SlidingSheetDialog 实例来实现。

void showAsBottomSheet() 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, '这是结果.'),
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: Text(
                      '这是面板的内容',
                      style: Theme.of(context).textTheme.body1,
                    ),
                  ),
                ),
              ),
            ),
          );
        },
      );
    }
  );

  print(result); // 这是结果。
}

结果:

Example

吸附

SlidingSheet 可以吸附到多个高度,也可以不吸附。可以通过传递 SnapSpec 实例来自定义吸附行为。

参数 描述
snap 如果为真,SlidingSheet 会吸附到提供的 snappings。否则,SlidingSheet 会从最小高度滑动到最大高度,然后开始滚动。
snappings 当用户结束拖动时,SlidingSheet 会吸附到这些高度。最小和最大值表示 SlidingSheet 滑动的边界。
positioning 可以设置为以下三个值之一:SnapPositioning.relativeToAvailableSpace - 相对于总可用空间定位吸附点。所有值必须在 0 到 1 之间。例如,在没有 AppBarScaffold 中,一个 0.5 的吸附点意味着吸附点位于屏幕高度的 40%,与 SlidingSheet 的高度无关。SnapPositioning.relativeToSheetHeight - 相对于 SlidingSheet 的总高度定位吸附点。所有值必须在 0 到 1 之间。例如,一个 0.5 的吸附点和一个 300 像素的总 SlidingSheet 高度意味着吸附点距离底部 150 像素。SnapPositioning.pixelOffset - 在固定像素偏移处定位吸附点。double.infinity 可以用来引用总可用空间而无需自己计算。
onSnap 一个回调函数,当 SlidingSheet 吸附到某个高度时被调用。

SnapPositioning.relativeToAvailableSpace with a snap of 0.5 SnapPositioning.relativeToSheetHeight with a snap of 0.5 SnapPositioning.pixelOffset with a snap of 100

还可以使用预构建的吸附点来吸附到头部或尾部,如示例所示。

吸附点 描述
SnapSpec.headerFooterSnap 使头部和尾部完全可见而不考虑 SlidingSheet 上的垂直填充。
SnapSpec.headerSnap 使头部完全可见而不考虑 SlidingSheet 上的顶部填充。
SnapSpec.footerSnap 使尾部完全可见而不考虑 SlidingSheet 上的底部填充。
SnapSpec.expanded 使整个 SlidingSheet 扩展。

控制器

SheetController 可以手动改变 SlidingSheet 的状态,只需将一个 SheetController 实例传递给 SlidingSheet。注意,方法只能在 SlidingSheet 渲染后使用,但提前调用它们不会抛出异常。

你还可以使用静态方法 SheetController.of(context) 获取最近的 SlidingSheetSheetController 实例。即使你没有显式地为 SlidingSheet 分配 SheetController,这也适用。

方法 描述
expand() SlidingSheet 展开到最大高度。
collapse() SlidingSheet 折叠到最小高度。
snapToExtent() SlidingSheet 吸附到任意高度。高度会被限制在最小和最大高度之间。如果滚动偏移量大于 0,则 SlidingSheet 会先滚动到顶部,然后再滑动到指定的高度。
scrollTo() SlidingSheet 滚动到给定的偏移量。如果 SlidingSheet 尚未达到最大高度,则会先吸附到最大高度,然后再滚动到给定的偏移量。
rebuild() 调用 SlidingSheet 的所有构建器重建其子项。此方法可以在不调用父级小部件的 setState(() {}); 的情况下反映 SlidingSheet 子项的变化以提高性能。
show() 如果 SlidingSheet 之前隐藏了,将它视觉上显示出来。注意,对 SlidingSheetDialogs 调用此方法不会产生影响。
hide() 视觉上隐藏 SlidingSheet,直到你再次调用 show()。注意,对 SlidingSheetDialogs 调用此方法不会产生影响。

头部和尾部

头部和尾部是 SlidingSheet 的 UI 元素,它们分别在 SlidingSheet 的顶部和底部显示,并且不会滚动。可滚动的内容将在头部和尾部之间。触摸事件将自动委托给 SlidingSheet。示例如下:

@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.grey.shade200,
    appBar: AppBar(
      title: Text('简单示例'),
    ),
    body: Stack(
      children: <Widget>[
        SlidingSheet(
          elevation: 8,
          cornerRadius: 16,
          snapSpec: const SnapSpec(
            snap: true,
            snappings: [112, 400, double.infinity],
            positioning: SnapPositioning.pixelOffset,
          ),
          builder: (context, state) {
            return Container(
              height: 500,
              child: Center(
                child: Text(
                  '这是面板的内容',
                  style: Theme.of(context).textTheme.body1,
                ),
              ),
            );
          },
          headerBuilder: (context, state) {
            return Container(
              height: 56,
              width: double.infinity,
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                '这是头部',
                style: Theme.of(context).textTheme.body1.copyWith(color: Colors.white),
              ),
            );
          },
          footerBuilder: (context, state) {
            return Container(
              height: 56,
              width: double.infinity,
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                '这是尾部',
                style: Theme.of(context).textTheme.body1.copyWith(color: Colors.black),
              ),
            );
          },
        ),
      ],
    ),
  );
}

结果:

Simple header/footer example

ListView 和 Column

SlidingSheet 的子元素不允许具有无限(无界)的高度。因此,当使用 ListView 时,请确保将 shrinkWrap 设置为 true 并将 physics 设置为 NeverScrollableScrollPhysics。同样,当使用 Column 作为 SlidingSheet 的子元素时,请确保将 mainAxisSize 设置为 MainAxisSize.min

物料效果

为了在与面板交互时更改 UI,你可以传递一个回调到 SlidingSheetlistener 字段,该字段会在面板滑动或滚动时调用当前的 SheetState。你可以根据这些变化重新构建你的 UI。当使用 SlidingSheet 作为 bottomSheetDialog 时,你也可以使用 SheetController.rebuild() 来重建面板,如果你想更改某些参数。

为了重新构建 SlidingSheet 的单个子项(例如,当内容滚动到头部下方时提升头部),你也可以使用 SheetListenerBuilder

return SheetListenerBuilder(
  // buildWhen 可以用于仅在必要时重新构建小部件。
  buildWhen: (oldState, newState) => oldState.isAtTop != newState.isAtTop,
  builder: (context, state) {
    return AnimatedContainer(
      elevation: !state.isAtTop ? elevation : 0.0,
      duration: const Duration(milliseconds: 400),
      child: child,
    );
  },
);

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

1 回复

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


sliding_sheet_new 是一个用于在 Flutter 应用中创建滑动底部面板的插件。它提供了灵活的配置选项,允许开发者自定义面板的滑动行为、外观和动画效果。以下是使用 sliding_sheet_new 插件的基本步骤和示例代码。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 sliding_sheet_new 依赖:

dependencies:
  flutter:
    sdk: flutter
  sliding_sheet_new: ^0.6.3  # 请使用最新版本

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

2. 基本使用

以下是一个简单的示例,展示如何使用 sliding_sheet_new 创建一个滑动底部面板。

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Sliding Sheet Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              showSlidingSheet(
                context,
                builder: (context) {
                  return SlidingSheet(
                    elevation: 8,
                    cornerRadius: 16,
                    snapSpec: const SnapSpec(
                      snappings: [0.4, 0.7, 1.0],
                      positioning: SnapPositioning.relativeToAvailableSpace,
                    ),
                    builder: (context, state) {
                      return Material(
                        color: Colors.white,
                        child: Column(
                          children: [
                            Container(
                              height: 50,
                              alignment: Alignment.center,
                              child: Text(
                                'Sliding Sheet',
                                style: TextStyle(
                                  fontSize: 20,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                            Expanded(
                              child: ListView.builder(
                                itemCount: 20,
                                itemBuilder: (context, index) {
                                  return ListTile(
                                    title: Text('Item $index'),
                                  );
                                },
                              ),
                            ),
                          ],
                        ),
                      );
                    },
                  );
                },
              );
            },
            child: Text('Show Sliding Sheet'),
          ),
        ),
      ),
    );
  }
}
回到顶部