Flutter可拖拽底部面板插件draggable_sheet的使用

Flutter可拖拽底部面板插件draggable_sheet的使用

Draggable Sheet 是一个 Flutter 包,使开发者能够在应用中实现一个可自定义、交互性强的底部面板,并且该面板的高度可以动态调整,展示优雅的项目。它通过提供更复杂的控制来扩展了典型的可拖拽面板功能,提供了更丰富的用户交互体验。

特性

  • 动态高度调整:根据内容或预设限制调整底部面板的高度。
  • 项目交互:点击项目进行交互或选择,面板会根据上下文做出响应。
  • 自定义动画和捕捉:平滑的动画效果和在不同高度处的可选捕捉点。
  • 响应式设计:适应不同的屏幕尺寸和方向。

安装

要在你的 Flutter 项目中添加 Draggable Sheet,编辑你的 pubspec.yaml 文件:

dependencies:
  draggable_sheet: ^1.0.1+3

然后,在你的 Dart 代码中导入包:

import 'package:draggable_sheet/draggable_sheet.dart';

使用

此包提供了一个 DraggableSheet 小部件,可以包含在你的 Flutter 应用程序中。以下是一个简单的示例,说明如何将它集成到你的应用中:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: DraggableSheet(
          minHeight: 0.1,
          maxHeight: 0.8,
          itemHeight: 50,
          list: [
            (Widget: Text('Item 1'), index: 0),
            (Widget: Text('Item 2'), index: 1),
          ],
          didSelectItem: (index) {
            print('Selected item $index');
          },
        ),
      ),
    );
  }
}

配置

  • minHeight: 可拖拽面板能占据的屏幕高度的最小比例。
  • maxHeight: 可拖拽面板能占据的屏幕高度的最大比例。
  • itemHeight: 可拖拽面板中每个项目的高度。
  • list: 一个包含元组的列表,每个元组包含一个 Widget 和其对应的索引。
  • didSelectItem: 当项目被选中时调用的回调函数。

示例代码

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

import 'dart:math';

import 'package:draggable_sheet/draggable_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var list = List.generate(10, (index) {
    return (
      Colors.primaries[Random().nextInt(Colors.primaries.length)].withOpacity(1),
      index,
    );
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            height: 100 + kBottomNavigationBarHeight,
            child: Row(
              children: [
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: SizedBox(
                      height: 100,
                      child: TextFormField(
                        decoration: const InputDecoration(
                          label: Padding(
                            padding: EdgeInsets.all(0),
                            child: Text("Enter the number of cards"),
                          ),
                          labelStyle: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.w500,
                            // height: 0,
                          ),
                          floatingLabelAlignment: FloatingLabelAlignment.start,
                        ),
                        textInputAction: TextInputAction.done,
                        keyboardType: TextInputType.number,
                        inputFormatters: [
                          FilteringTextInputFormatter.digitsOnly,
                        ],
                        textAlign: TextAlign.start,
                        onTapOutside: (event) {
                          FocusScope.of(context).unfocus();
                        },
                        onChanged: (value) {
                          final intValue = int.tryParse(value) ?? 1;
                          setState(() {
                            list = List.generate(intValue, (index) {
                              return (
                                Colors.primaries[Random().nextInt(Colors.primaries.length)]
                                    .withOpacity(1),
                                index
                              );
                            });
                          });
                        },
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
          Positioned.fill(
            child: () {
              final mediaQuery = MediaQuery.of(context);
              final height = mediaQuery.size.height;
              return DraggableSheet(
                minHeight: (kBottomNavigationBarHeight * 2 + (0.25 * height)) / height,
                maxHeight: 1,
                itemHeight: 0.25 * height,
                list: List.generate(list.length, (index) {
                  return (
                    HomeProfileItemView(
                      index: index,
                      itemHeight: 0.25 * height,
                      item: list[index],
                    ),
                    index
                  );
                }),
                didSelectItem: (index) {
                  var tempList = List<(Color, int)>.from(list);
                  final tempSelectedItem = tempList[index];
                  tempList.removeAt(index);
                  tempList.insert(tempList.length, tempSelectedItem);
                  setState(() {
                    list = tempList;
                  });
                },
              );
            }(),
          ),
        ],
      ),
    );
  }
}

class HomeProfileItemView extends StatefulWidget {
  const HomeProfileItemView({
    super.key,
    required this.index,
    required this.itemHeight,
    required this.item,
    this.onTap,
  });

  final int index;
  final double itemHeight;
  final (Color, int) item;
  final void Function()? onTap;

  [@override](/user/override)
  State<HomeProfileItemView> createState() => _HomeProfileItemViewState();
}

class _HomeProfileItemViewState extends State<HomeProfileItemView> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.onTap,
      child: Card(
        color: Colors.transparent,
        elevation: 0,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(15),
        ),
        child: SizedBox(
          height: widget.itemHeight,
          child: Container(
            decoration: BoxDecoration(
              color: widget.item.$1,
              borderRadius: BorderRadius.circular(15),
            ),
            alignment: Alignment.center,
            child: Text(
              widget.item.$2.toString(),
              style: const TextStyle(
                fontSize: 26,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何使用 draggable_sheet 插件在 Flutter 中实现可拖拽底部面板的示例代码。draggable_sheet 插件允许你创建一个可以像 iOS 的 Draggable Bottom Sheet 那样拖动的面板。

首先,确保你已经在 pubspec.yaml 文件中添加了 draggable_sheet 依赖:

dependencies:
  flutter:
    sdk: flutter
  draggable_sheet: ^latest_version  # 请替换为最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来是一个完整的示例代码,展示了如何使用 draggable_sheet

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey<DraggableSheetState> _draggableSheetKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Draggable Sheet Example'),
      ),
      body: Column(
        children: [
          Expanded(
            child: Center(
              child: Text('Main Content'),
            ),
          ),
          DraggableSheet(
            key: _draggableSheetKey,
            initialExtent: 0.3,
            minExtent: 0.1,
            maxExtent: 1,
            builder: (context, controller) {
              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(
                        'Draggable Bottom Sheet',
                        style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                      ),
                      SizedBox(height: 16),
                      Text(
                        'You can drag this sheet up and down.',
                        style: TextStyle(fontSize: 16),
                      ),
                      SizedBox(height: 16),
                      ElevatedButton(
                        onPressed: () {
                          _draggableSheetKey.currentState?.close();
                        },
                        child: Text('Close'),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _draggableSheetKey.currentState?.expand();
        },
        tooltip: 'Open Sheet',
        child: Icon(Icons.add),
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个 MyApp 小部件,它是应用的根小部件。
  2. MyHomePage 是主页,它包含一个 Scaffold,其中包含一个 AppBar 和一个 Column
  3. Column 包含了一个 Expanded 小部件,用于显示主内容,以及一个 DraggableSheet 小部件。
  4. DraggableSheet 小部件使用了一个 GlobalKey,以便我们可以在其他地方控制它(例如,打开或关闭它)。
  5. DraggableSheetbuilder 参数接收一个构建器函数,用于构建面板的内容。
  6. 面板内容是一个简单的 Container,其中包含一些文本和一个关闭按钮。
  7. 一个 FloatingActionButton 被添加到 ScaffoldfloatingActionButton 属性中,用于打开面板。

你可以根据需要调整 initialExtentminExtentmaxExtent 的值来控制面板的初始高度、最小高度和最大高度。此外,你可以通过调用 _draggableSheetKey.currentState?.expand()_draggableSheetKey.currentState?.close() 来编程控制面板的展开和关闭。

回到顶部