{"id":21286624,"url":"https://github.com/moazelsawaf/dash_bubble","last_synced_at":"2025-10-24T04:03:57.503Z","repository":{"id":104211219,"uuid":"609355318","full_name":"moazelsawaf/dash_bubble","owner":"moazelsawaf","description":"A Flutter plugin that allows you to create a floating bubble on the screen 💙","archived":false,"fork":false,"pushed_at":"2024-06-29T10:56:14.000Z","size":1629,"stargazers_count":50,"open_issues_count":9,"forks_count":30,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-07T12:45:01.600Z","etag":null,"topics":["bubble","floating-bubbles","flutter","overlay","pub"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/dash_bubble","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moazelsawaf.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-03-03T23:59:37.000Z","updated_at":"2025-04-19T17:30:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"f2d50adf-5c21-4479-bea9-4137b939d9b3","html_url":"https://github.com/moazelsawaf/dash_bubble","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/moazelsawaf/dash_bubble","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moazelsawaf%2Fdash_bubble","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moazelsawaf%2Fdash_bubble/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moazelsawaf%2Fdash_bubble/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moazelsawaf%2Fdash_bubble/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moazelsawaf","download_url":"https://codeload.github.com/moazelsawaf/dash_bubble/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moazelsawaf%2Fdash_bubble/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273707644,"owners_count":25153726,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bubble","floating-bubbles","flutter","overlay","pub"],"created_at":"2024-11-21T11:30:43.324Z","updated_at":"2025-10-24T04:03:52.455Z","avatar_url":"https://github.com/moazelsawaf.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://raw.githubusercontent.com/moazelsawaf/dash_bubble/main/doc/assets/package_banner.png\" width=\"100%\" alt=\"Dash Bubble Banner\" /\u003e\n\u003ch2 align=\"center\"\u003e\n  Dash Bubble\n\u003c/h2\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://flutter.dev\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Platform-Flutter-02569B?logo=flutter\" alt=\"Platform\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://pub.dartlang.org/packages/dash_bubble\"\u003e\n    \u003cimg alt=\"Pub Package\" src=\"https://img.shields.io/pub/v/dash_bubble.svg?color=blue\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/BSD-3-Clause\"\n  rel=\"ugc\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-BSD_3--Clause-red.svg\" alt=\"License: BSD-3-Clause\"\u003e\u003c/a\u003e\n  \u003cbr\u003e\n  \u003ca href=\"https://github.com/moazelsawaf/dash_bubble\" rel=\"ugc\"\u003e\u003cimg   src=\"https://img.shields.io/github/languages/code-size/moazelsawaf/dash_bubble.svg\" alt=\"GitHub code size in bytes\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/moazelsawaf/dash_bubble\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/stars/moazelsawaf/dash_bubble.svg?style=flat\u0026logo=github\u0026colorB=ffcc00\u0026label=stars\" alt=\"Star on GitHub\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/moazelsawaf/dash_bubble/issues\" rel=\"ugc\"\u003e\u003cimg   src=\"https://img.shields.io/github/issues/moazelsawaf/dash_bubble.svg?color=DF1304\" alt=\"GitHub Open Issues\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/moazelsawaf/dash_bubble/commits/main\" rel=\"ugc\"\u003e\u003cimg   src=\"https://img.shields.io/github/last-commit/moazelsawaf/dash_bubble.svg\" alt=\"GitHub Last Commit Date\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## 💡 Overview\n\nA Flutter plugin that allows you to create a floating bubble on the screen built on top of [Floating-Bubble-View](https://github.com/TorryDo/Floating-Bubble-View) library for Android.\n\n*The plugin currently supports **Android** only and **doesn't support IOS because** the feature of drawing over other apps is not available there*\n\n\u003cbr\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/moazelsawaf/dash_bubble/main/doc/assets/animated_example.webp\" width=\"25%\" alt=\"Animated Example\" /\u003e\n\u003cbr\u003e\nThis GIF is taken from the \u003ca href=\"https://github.com/moazelsawaf/dash_bubble/tree/main/example\"\u003eExample Project\u003c/a\u003e\n\u003c/p\u003e\n\n## 🚧 Breaking Changes\n\n### v2.0.0\n\n* 🚚 rename `requestPermission()` method to `requestOverlayPermission()`.\n* 🚚 rename `hasPermission()` method to `hasOverlayPermission()`.\n* 🚚 rename `options` parameter in `startBubble()` method to `bubbleOptions`.\n* ✨ add `notificationOptions` parameter to `startBubble()` method and move the notification options from `bubbleOptions` to the new `notificationOptions`.\n* 🛂 starting from Android 13 (Tiramisu), the service notification will not be shown unless the **POST_NOTIFICATIONS** permission is granted at the runtime, refer to the [Service Notification](#-service-notification) section for details.\n\n### v1.0.0\n\n* 🚚 rename `onBubbleTap()` callback to `onTap()` in `startBubble()` method.\n* ✨ convert the values of `startLocationX` and `startLocationY` to be in density-independent pixels (dp) instead of pixels (px) as per Flutter convention.\n\n## 🔧 Setup\n\nSet the minimum SDK version to `21` or higher in your `android/app/build.gradle` file:\n\n```gradle\nandroid {\n    defaultConfig {\n        ...\n        minSdkVersion 21 // Set this to 21 or higher\n        ...\n    }\n}\n```\n\nThe plugin uses these two permissions but **you don't need to add them** to your `AndroidManifest.xml` file because the plugin will add them automatically:\n\n```xml\n\u003cuses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\" /\u003e\n\u003cuses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" /\u003e\n\u003cuses-permission android:name=\"android.permission.POST_NOTIFICATIONS\" /\u003e\n```\n\n## 💻 Usage\n\nImport the package:\n\n```dart\nimport 'package:dash_bubble/dash_bubble.dart';\n```\n\nUse the singleton instance of `DashBubble` to access all the available methods, for example:\n\n```dart\nDashBubble.instance.requestPermission()\nDashBubble.instance.startBubble()\n```\n\n📘 You can checkout the complete API Reference [here](https://pub.dev/documentation/dash_bubble/latest/)\n\n## 🧰 Available Methods\n\n### Notes\n\n* All the methods are asynchronous and has a return type of `Future\u003cbool\u003e`.\n* All the methods returns `false` if the platform is not **Android**.\n\n| Method | Description | Parameters | Behavior | Notes |\n| --- | --- | --- | --- | --- |\n| `requestOverlayPermission()` | Requests the permission to draw over other apps (Overlay) | - | Returns `true` if the permission is granted, `false` otherwise | If the permission is already granted, this method will return `true` without asking the user\u003cbr\u003e\u003cbr\u003eIn Android versions prior to `Android 6.0 (M)`, this method will return `true` without asking the user |\n| `hasOverlayPermission()` | Checks if the permission to draw over other apps is granted (Overlay) | - | Returns `true` if the permission is granted, `false` otherwise | In Android versions prior to `Android 6.0 (M)`, this method will always return `true` |\n| `requestPostNotificationsPermission()` | Requests the permission to post notifications (Used to customize the Service Notification) | - | Returns `true` if the permission is granted, `false` otherwise\u003cbr\u003e\u003cbr\u003eIf the Android version is prior to `Android 13 (Tiramisu)`, or if the permission is already granted, this method will return `true` without asking the user. | The user can be asked for the permission only twice, if the user denied the permission twice, the function would not be able to ask for the permission anymore and it will return false, however, the user can still grant the permission manually from the app settings page.\u003cbr\u003e\u003cbr\u003eStarting from Android 13 (Tiramisu), the service notification will not be shown unless the **POST_NOTIFICATIONS** permission is granted at the runtime |\n| `hasPostNotificationsPermission()` | Checks if the permission to post notifications is granted | - | Returns `true` if the permission is granted, `false` otherwise | If the Android version is prior to `Android 13 (Tiramisu)`, this method will always return `true` |\n| `isRunning()` | Checks if the bubble is currently running | - | Returns `true` if the bubble is running, `false` otherwise | The bubble is considered running if it is visible on the screen |\n| `startBubble()` | Starts the bubble | BubbleOptions? bubbleOptions\u003cbr\u003e\u003cbr\u003eNotificationOptions? notificationOptions\u003cbr\u003e\u003cbr\u003e[Available Callbacks](#-available-callbacks) | Returns `true` if the bubble started successfully, `false` otherwise | If the bubble is already running or the permission is not granted, this method will return `false` |\n| `stopBubble()` | Stops the bubble | - | Returns `true` if the bubble stopped successfully, `false` otherwise | If the bubble is not running, this method will return `false` |\n\n## 📝 Bubble Customization Options\n\n**Note**: All the options are optional and you can pass only the options you want to customize.\n\n| Option | Description | Default | Notes |\n| --- | --- | --- | --- |\n| `bubbleIcon` | The icon of the bubble | `null` | The icon is set as an image file placed inside `android\\app\\src\\main\\res\\drawable\\` and the value of the parameter should be the the file name **without the extension**\u003cbr\u003e\u003cbr\u003eIf not provided, the icon will be the plugin icon |\n| `closeIcon` | The icon of the close button | `null` | The icon is set as an image file placed inside `android\\app\\src\\main\\res\\drawable\\` and the value of the parameter should be the the file name **without the extension**\u003cbr\u003e\u003cbr\u003eIf not provided, there will be a default close icon |\n| `startLocationX` | The initial starting position of the bubble on the x axis | `0` | - |\n| `startLocationY` | The initial starting position of the bubble on the y axis | `200` | - |\n| `bubbleSize` | The size of the bubble | `60` | - |\n| `opacity` | The opacity of the bubble | `1.0` | The value must be between `0.0` and `1.0` |\n| `enableClose` | Whether to show the close button or not | `true` | - |\n| `closeBehavior` | The behavior of the close button | `CloseBehavior.following` | The value must be a member of `CloseBehavior` enum\u003cbr\u003e\u003cbr\u003eAvailable values:\u003cbr\u003e`CloseBehavior.following`\u003cbr\u003e`CloseBehavior.fixed` |\n| `distanceToClose` |The distance between the bubble and the bottom edge of the screen to show the close button | `100` | - |\n| `enableAnimateToEdge` | Whether to animate the bubble to the edge of the screen when it is dragged to the edge of the screen or not | `true` | - |\n| `enableBottomShadow` | Whether to show the bottom shadow behind the close button of the bubble or not | `true` | - |\n| `keepAliveWhenAppExit` | Whether to keep the bubble alive when the app is closed or not | `false` | - |\n\n## 📞 Available Callbacks\n\n**Note**: All the callbacks are optional and they all can be passed as parameters to the `startBubble()` method.\n\n| Callback | Description | Parameters | Notes |\n| --- | --- | --- | --- |\n| `onTap` | Called when the bubble is tapped | - | - |\n| `onTapDown` | Called when the bubble is tapped down (pressed) | `double x`\u003cbr\u003e`double y` | The parameters `x` and `y` are the coordinates of the bubble when it is tapped down |\n| `onTapUp` | Called when the bubble is tapped up (released) | `double x`\u003cbr\u003e`double y` | The parameters `x` and `y` are the new coordinates of the bubble after it is tapped up |\n| `onMove` | Called when the bubble is moved | `double x`\u003cbr\u003e`double y` | The parameters `x` and `y` are the new coordinates of the bubble after it is moved |\n\n## 🔔 Service Notification\n\nThe service notification is a non-dismissible notification that is shown when the bubble is running to keep the service alive.\n\nThe notification is shown automatically when the bubble is started and hidden automatically when the bubble is stopped.\n\n*Currently, their is no way to disable the notification.*\n\n**Note**: Starting from `Android 13 (Tiramisu)`, the **POST_NOTIFICATIONS** permission must be granted to show the notification, however, you don't need to add the permission to the `AndroidManifest.xml` file because it is already added by the plugin, but you need to request it at the runtime, otherwise the notification will not be shown.\n\nThis permission can be requested by calling `requestPostNotificationsPermission()` method and can be checked by calling `hasPostNotificationsPermission()` method.\n\nIf the permission is not granted, the notification will not be shown but the bubble will still work normally.\n\n### Customization Options\n\nThe service notification can be optionally customized by passing a `notificationOptions` parameter to the `startBubble()` method.\n\n**Note**: All the options are optional and you can pass only the options you want to customize. Here is a list of the available options in the `notificationOptions` parameter:\n\n| Option | Description | Default | Notes |\n| --- | --- | --- | --- |\n| `id` | The id of the service notification | `101` | - |\n| `title` | The title of the service notification | `null` | If not provided, the title will be the app name |\n| `body` | The body of the service notification | `null` | If not provided, there will be no notification body |\n| `icon` | The icon of the service notification | `null` | The icon is set as an image file placed inside `android\\app\\src\\main\\res\\drawable\\` and the value of the parameter should be the the file name **without the extension**\u003cbr\u003e\u003cbr\u003eIf not provided, the icon will be the plugin icon |\n| `channelId` | The channel id of the service notification | `bubble_notification` | - |\n| `channelName` | The channel name of the service notification | `Bubble Notification` | - |\n  \n## ✅ Roadmap\n\n* [ ] Add Tests 🧪\n* [ ] Implement a ready-to-use `AppBubble` which starts automatically when the app is on the background and stops when the app is on the foreground and has the ability to bring the app to the foreground when the bubble is tapped 📱\n* [ ] Ability to pass a `Widget` as the `bubbleIcon` and `closeIcon` 💪🏻\n* [ ] Implement the `ExpandableView` feature in the original library ⚡\n* [x] Implement the the rest of the available callbacks in the original library `onMove(x,y)`, `onUp(x,y)`, and `onDown(x,y)` 🔗\n\n## 💪🏻 Contribution Guide\n\nI would be happy to have your contributions 💙\n\nIf you find a bug or want a feature, but don't know how to fix/implement it, please fill an [Issue](https://github.com/moazelsawaf/dash_bubble/issues).  \nIf you fixed a bug or implemented a feature, please send a [Pull Request](https://github.com/moazelsawaf/dash_bubble/pulls).\n\n\u003ca href=\"https://github.com/moazelsawaf/dash_bubble/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=moazelsawaf/dash_bubble\" /\u003e\n\u003c/a\u003e\n\nMade with [contrib.rocks](https://contrib.rocks).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoazelsawaf%2Fdash_bubble","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoazelsawaf%2Fdash_bubble","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoazelsawaf%2Fdash_bubble/lists"}