Flutter悬浮拖拽组件插件mek_floating_drag的使用

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

Flutter悬浮拖拽组件插件mek_floating_drag的使用

通过mek_floating_drag插件,你可以实现一个可以拖动的组件,并且在特定条件下可以被移除或者隐藏。

特性

  • ✅ 可以拖到任何你想要的地方
  • ✅ 按钮会吸附到容器边缘,弹跳效果
  • ✅ 如果按钮释放时超出自然边缘,它会被吸回容器内
  • ✅ 按钮会在一段时间后隐藏
  • ✅ 如果不与按钮互动,或者与其他物体碰撞,按钮也会隐藏
  • ✅ 你可以通过将按钮拖到指定区域(垃圾桶)来删除它
  • ✅ 当按钮被释放到垃圾桶内时,它会缩小并居中对齐于垃圾桶中心
  • ❌ 当按钮接近垃圾桶时,它会被吸引到垃圾桶

开始使用

首先,确保所有内容都包裹在一个FloatingZone内。

使用示例

定义可拖动的组件

final draggable = FloatingDraggable(
  controller: _dartController,
  naturalEdgesResolver: (containerSize, childSize) {
    return const EdgeInsets.symmetric(horizontal: double.nan, vertical: 16.0);
  },
  elasticEdgesResolver: (containerSize, childSize) {
    return const EdgeInsets.symmetric(horizontal: 16.0, vertical: double.nan);
  },
  retractEdgesResolver: (containerSize, childSize) {
    return EdgeInsets.symmetric(horizontal: -(0.60 * childSize.width), vertical: double.nan);
  },
  child: FloatingActionButton(
    onPressed: () {},
    child: const Icon(Icons.message),
  ),
);

定义一个目标区域

该目标区域用于删除可拖动组件。

const dragTargetBin = FloatingCircularDragBin();

将所有内容包裹在FloatingZone

这是确保组件正确工作的必要步骤。也可以使用FloatingZone.inOverlay

final result = FloatingZone.inStack(
  entries: [
    const Positioned(
      bottom: 16.0,
      right: 0.0,
      left: 0.0,
      child: dragTargetBin,
    ),
    Positioned(
      bottom: 16.0,
      right: 16.0,
      child: draggable,
    ),
  ],
  child: RestrictedFloatingZone(
    child: scaffold,
  ),
);

额外信息

如果你使用了RestrictedFloatingZone,则可以在用户按下RestrictedFloatingZone时隐藏可拖动组件。

完整示例代码

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Mek Floating Drag',
      theme: ThemeData(
        primarySwatch: Colors.deepPurple,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  late final _draggableController = FloatingDraggableController(vsync: this);

  [@override](/user/override)
  void dispose() {
    _draggableController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    final scaffold = Scaffold(
      appBar: AppBar(
        title: const Text('Mek Floating Drag'),
        actions: [
          AnimatedBuilder(
            animation: _draggableController.visibilityAnimation,
            child: IconButton(
              onPressed: () => _draggableController.show(),
              icon: const Icon(Icons.add),
            ),
            builder: (context, child) {
              return Transform.scale(
                scale: 1 - _draggableController.visibilityAnimation.value,
                transformHitTests: false,
                child: child!,
              );
            },
          ),
        ],
      ),
      body: SingleChildScrollView(
        child: Column(
          children: Colors.primaries.reversed.map((color) {
            return Container(
              height: 100.0,
              color: color,
            );
          }).toList(),
        ),
      ),
    );

    const dragTargetBin = FloatingCircularDragBin();

    final draggable = FloatingDraggable(
      controller: _draggableController,
      naturalEdgesResolver: (containerSize, childSize) {
        return const EdgeInsets.symmetric(horizontal: double.nan, vertical: 16.0);
      },
      elasticEdgesResolver: (containerSize, childSize) {
        return const EdgeInsets.symmetric(horizontal: 16.0, vertical: double.nan);
      },
      retractEdgesResolver: (containerSize, childSize) {
        return EdgeInsets.symmetric(horizontal: -(0.60 * childSize.width), vertical: double.nan);
      },
      child: FloatingActionButton(
        onPressed: () => ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          duration: const Duration(seconds: 1),
          content: Text('Tapped!'),
        )),
        child: const Icon(Icons.message),
      ),
    );

    final result = FloatingZone.inStack(
      entries: [
        const Positioned(
          bottom: 16.0,
          right: 0.0,
          left: 0.0,
          child: dragTargetBin,
        ),
        Positioned(
          bottom: 16.0,
          right: 16.0,
          child: draggable,
        ),
      ],
      child: RestrictedFloatingZone(
        child: scaffold,
      ),
    );

    return result;
  }
}

更多关于Flutter悬浮拖拽组件插件mek_floating_drag的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter悬浮拖拽组件插件mek_floating_drag的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


mek_floating_drag 是一个 Flutter 插件,用于创建可以悬浮并拖拽的组件。这个插件非常适合需要在应用中实现可拖拽悬浮窗口、面板或其他界面元素的场景。

安装

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

dependencies:
  mek_floating_drag: ^0.0.1  # 请确认最新的版本号

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

基本用法

mek_floating_drag 提供了一个 FloatingDrag 组件,你可以将它包裹在任何你想要实现拖拽功能的子组件上。

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

class FloatingDragExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Floating Drag Example'),
      ),
      body: Center(
        child: FloatingDrag(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
            child: Center(
              child: Text(
                'Drag Me',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

void main() => runApp(MaterialApp(
  home: FloatingDragExample(),
));

主要特性

  1. 拖拽功能: FloatingDrag 组件允许用户通过触摸并拖动来移动子组件。
  2. 边界限制: 你可以通过设置 constraints 参数来限制拖拽的范围。
  3. 动画效果: 支持在拖拽结束时添加动画效果,使组件平滑地回到边界内。

高级用法

1. 设置拖拽范围

你可以通过 constraints 参数来限制拖拽的范围。例如,限制拖拽在屏幕范围内:

FloatingDrag(
  constraints: BoxConstraints(
    minWidth: 0,
    maxWidth: MediaQuery.of(context).size.width,
    minHeight: 0,
    maxHeight: MediaQuery.of(context).size.height,
  ),
  child: Container(
    width: 100,
    height: 100,
    color: Colors.blue,
    child: Center(
      child: Text(
        'Drag Me',
        style: TextStyle(color: Colors.white),
      ),
    ),
  ),
),

2. 添加动画效果

你可以通过 onDragEnd 回调来实现自定义的动画效果。例如,在拖拽结束时让组件返回原位:

FloatingDrag(
  onDragEnd: (details, offset) {
    // 在这里实现自定义的动画效果
  },
  child: Container(
    width: 100,
    height: 100,
    color: Colors.blue,
    child: Center(
      child: Text(
        'Drag Me',
        style: TextStyle(color: Colors.white),
      ),
    ),
  ),
),

3. 自定义拖拽行为

你可以通过 dragBehavior 参数来自定义拖拽行为,例如只允许水平或垂直拖拽:

FloatingDrag(
  dragBehavior: DragBehavior.horizontal,  // 只允许水平拖拽
  child: Container(
    width: 100,
    height: 100,
    color: Colors.blue,
    child: Center(
      child: Text(
        'Drag Me',
        style: TextStyle(color: Colors.white),
      ),
    ),
  ),
),
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!