{"id":37166314,"url":"https://github.com/hyuwah/draggableview","last_synced_at":"2026-01-14T19:42:38.463Z","repository":{"id":62821675,"uuid":"168088568","full_name":"hyuwah/DraggableView","owner":"hyuwah","description":"DraggableView is an Android library to make floating draggable view easily using extensions on Kotlin \u0026 provided utils class on Java","archived":false,"fork":false,"pushed_at":"2023-07-19T12:05:25.000Z","size":243,"stargazers_count":116,"open_issues_count":7,"forks_count":21,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-24T08:36:58.442Z","etag":null,"topics":["android","android-library","draggable","library"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hyuwah.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2019-01-29T04:24:09.000Z","updated_at":"2025-05-21T11:02:40.000Z","dependencies_parsed_at":"2024-01-25T02:03:14.840Z","dependency_job_id":"303a9fcd-0d47-43f9-bcc6-e468df1746d6","html_url":"https://github.com/hyuwah/DraggableView","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/hyuwah/DraggableView","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyuwah%2FDraggableView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyuwah%2FDraggableView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyuwah%2FDraggableView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyuwah%2FDraggableView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hyuwah","download_url":"https://codeload.github.com/hyuwah/DraggableView/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyuwah%2FDraggableView/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28432680,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["android","android-library","draggable","library"],"created_at":"2026-01-14T19:42:37.920Z","updated_at":"2026-01-14T19:42:38.454Z","avatar_url":"https://github.com/hyuwah.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DraggableView\n[![](https://jitpack.io/v/hyuwah/DraggableView.svg)](https://jitpack.io/#hyuwah/DraggableView)\n\nDraggableView is an Android library to make floating draggable view easy. \n\nThis library basically wrap your view into DraggableView object, overriding it's onTouchListener and adds some extra utilities\n\n## Preview\n\n\u003cpre\u003e\n\u003cimg src=\"https://res.cloudinary.com/hyuwah-github-io/image/upload/v1611740627/DraggableView/basic_example.gif\" width=\"30%\"\u003e   \u003cimg src=\"https://res.cloudinary.com/hyuwah-github-io/image/upload/v1611740628/DraggableView/scrolling_example.gif\" width=\"30%\"\u003e   \u003cimg src=\"https://res.cloudinary.com/hyuwah-github-io/image/upload/v1611740632/DraggableView/overlay_other_app_example.gif\" width=\"30%\"\u003e\n\u003c/pre\u003e\n\n## Setup \nIn your root gradle add dependency to Jitpack:\n```gradle\n// project build.gradle\nallprojects {\n    repositories {\n        ...\n        maven { url 'https://jitpack.io' }\n    }\n}\n```\nIn you module gradle add dependency to library:\n```gradle\n// module / app build.gradle\ndependencies {\n    ...\n    implementation 'com.github.hyuwah:DraggableView:LatestVersion'\n}\n```\n\n\u003cdiv style=\"display:flex\"\u003e\n    \u003cp style=\"margin-right:8px\"\u003eLatest Version:\u003c/p\u003e\n    \u003ca href=\"https://jitpack.io/#hyuwah/DraggableView\"\u003e\n        \u003cimg src=\"https://jitpack.io/v/hyuwah/DraggableView.svg\" /\u003e\n    \u003c/a\u003e\n\u003c/div\u003e\n\n## Contributors\n\n\u003ca href=\"https://github.com/hyuwah/draggableview/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=hyuwah/draggableview\" /\u003e\n\u003c/a\u003e\n\n## Documentation\n\n### Basic Usage\n\n```kotlin\n// Need to declare draggable view in your activity / fragment\nprivate lateinit var someDraggableView: DraggableView\u003cImageView\u003e // can be other type of View or ViewGroup\n\n// ... When setting up the view (i.e. onCreate) ...\n\n// assign via DraggableView class\nsomeDraggableView = DraggableView.Builder(someView).build()\n\n// or assign via extensions\nsomeDraggableView = someView.setupDraggable().build() // setupDraggable() returns DraggableView.Builder\n\n// Above code will make `someView` draggable with default settings (Non-sticky / floating)\n```\n\n**Builder options**\n\nOptions|Parameter|Default|Description\n---|---|---|---\n`setStickyMode()` | `Draggable.Mode.NON_STICKY`, `Draggable.Mode.STICKY_X`, `Draggable.Mode.STICKY_Y`, `Draggable.Mode.STICKY_XY` | `Draggable.Mode.NON_STICKY` | Set stickiness mode\n`setAnimated()` | `true`, `false` | `true` | To animate the sticky movement, doesn't affect `NON_STICKY`\n`setListener()` | `null`, `DraggableListener` implementation | `null` | Listener for on view position's changed \u0026 on long click\n\n\n```kotlin\nprivate lateinit var someDraggableView: DraggableView\u003cImageView\u003e // can be other View or ViewGroup\n\n// ... inside onCreate\n// via DraggableView class with builder options\nsomeDraggableView = DraggableView.Builder(someView)\n                        .setStickyMode(DraggableView.Mode.NON_STICKY)\n                        .setListener(this)\n                        .build()\n// or via extensions with builder options\nsomeDraggableView = someView.setupDraggable()\n                        .setStickyMode(DraggableView.Mode.STICKY_X)\n                        .setAnimated(true)\n                        .build()\n\n```\n\n\n**Methods**\n\nMethod|Description\n---|---\n`getView()` | returns the original view\n`setViewPosition(x, y)` | programmatically set view position\n`enableDrag()` | enable draggable / override the onTouchListener\n`disableDrag()` | disable draggable / set the onTouchListener to null\n`show(duration)` | show the view with expanding animation (duration default to 300ms if omitted)\n`hide(duration)` | hide the view with shrinking animation (duration default to 300ms if omitted)\n`dockToEdge()` | dock the view to left or right (only applies to MODE.STICKY_X for now)\n`undock()` | undock the view if it's docked\n\n\nYou can still add click listener to your view as usual with `originalView.setOnClickListener` directly to your original view or via `wrappedDraggableView.getView().setOnClickListener`\n\nBut for long click listener, you **have to use the `DraggableListener` interface**, as setting `setOnLongClickListener` directly on the view will interfere / might not be working well with the draggable view behavior\n\n**Listener**\n\n```kotlin\nprivate var someDraggableListener = object: DraggableListener {\n    override fun onPositionChanged(view: View) {\n        // Here you can access x \u0026 y of the view while moving\n        Log.d(TAG, \"X: ${view.x.toString()}, Y: ${view.y.toString()}\")\n    }\n    override fun onLongPress(view: View) {\n        // Handle on long click\n    }\n}\n\n\n// set the listener when creating the draggable view\nsomeDraggableView = DraggableView.Builder(someView)\n    .setListener(someDraggableListener)\n    .build()\n\n// or to existing one\nanotherDraggableView.listener = someDraggableListener\n```\n\nCheck example module for actual implementation\n- [Basic Example (Kotlin)](https://github.com/hyuwah/DraggableView/blob/master/example/src/main/java/io/github/hyuwah/draggableview/BasicExampleActivity.kt)\n- [Basic Example (Java)](https://github.com/hyuwah/DraggableView/blob/master/example/src/main/java/io/github/hyuwah/draggableview/JavaMainActivity.java)\n- [Scrolling Activity (Kotlin)](https://github.com/hyuwah/DraggableView/blob/master/example/src/main/java/io/github/hyuwah/draggableview/ScrollingActivity.kt)\n\n### Draggable view over other App (Overlay)\n\n\u003e Tested working on API 25, 28 \u0026 29\n\u003e Not working as of now on API 19 (on investigation)\n\nThis is the simplest way to setup an overlay draggable view, assuming it will be started from an activity.\n\nIt's best to use foreground service for the overlay draggable view\n\nSome notes:\n* On the service, implement `OverlayDraggableListener`\n* We need to make the view programmatically, here i'm creating a TextView, you can also inflate a layout\n\n\n```kotlin\nclass OverlayService : Service(), OverlayDraggableListener {\n\n    private lateinit var overlayView: TextView\n    private var isOverlayOn = false\n    private var params: WindowManager.LayoutParams? = null\n    private lateinit var windowManager: WindowManager\n\n    override fun onBind(intent: Intent): IBinder? {\n        return null\n    }\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n        isOverlayOn = if(isOverlayOn){\n            windowManager.removeViewImmediate(overlayView)\n            false\n        } else {\n            windowManager.addView(overlayView, params)\n            true\n        }\n        return START_NOT_STICKY\n    }\n\n    override fun onCreate() {\n        super.onCreate()\n        windowManager = getSystemService(WINDOW_SERVICE) as WindowManager\n        initOverlayView()\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        if(isOverlayOn){\n            windowManager.removeViewImmediate(overlayView)\n        }\n        isOverlayOn = false\n    }\n\n    override fun onParamsChanged(updatedParams: WindowManager.LayoutParams) {\n        windowManager.updateViewLayout(overlayView, updatedParams)\n    }\n\n    private fun initOverlayView() {\n        overlayView = TextView(this)\n        overlayView.text = \"Overlay Text View\"\n        overlayView.textSize = 32f\n        overlayView.setTextColor(Color.rgb(255, 255, 0))\n        overlayView.setShadowLayer(10f, 5f, 5f, Color.rgb(56, 56, 56))\n        overlayView.setOnClickListener {\n            Toast.makeText(this, \"Overlay view clicked\", Toast.LENGTH_SHORT).show()\n        }\n\n        params = overlayView.makeOverlayDraggable(this)\n\n    }\n```\n\nYou also need to add some permission and define your service in manifest\n```xml\n\u003cmanifest\u003e\n    ...\n    \u003cuses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.ACTION_MANAGE_OVERLAY_PERMISSION\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\" /\u003e\n    ...\n    \u003capplication\u003e\n        ...\n        \u003cservice\n            android:name=\".overlay.OverlayService\"\n            android:enabled=\"true\"\n            android:exported=\"false\"\u003e\u003c/service\u003e\n        ...\n    \u003c/application\u003e\n\u003c/manifest\u003e\n```\n\nAlso, before starting the service, you need to check if the device support overlay and required permission\n\n```kotlin\n// in Activity\n\nprivate var isOverlayOn = false // Global flag to toggle start / stop service\n\n// Check draw over other app permission before starting the service\nprivate fun toggleOverlay() {\n        if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.M \u0026\u0026\n            !Settings.canDrawOverlays(this)\n        ) {\n            // Get permission first on Android M \u0026 above\n            val intent = Intent(\n                Settings.ACTION_MANAGE_OVERLAY_PERMISSION,\n                Uri.parse(\"package:$packageName\")\n            )\n            startActivityForResult(intent, 1234)\n        } else {\n            val i = Intent(this, OverlayService::class.java)\n            if (!isOverlayOn) {\n                // Show\n                startService(i)\n            } else {\n                // Hide\n                stopService(i)\n            }\n            isOverlayOn = !isOverlayOn\n        }\n    }\n```\n\nCheck the example here \n- [Activity (Kotlin)](https://github.com/hyuwah/DraggableView/blob/master/example/src/main/java/io/github/hyuwah/draggableview/OverlayDraggableActivity.kt)\n- [Service (Kotlin)](https://github.com/hyuwah/DraggableView/blob/master/example/src/main/java/io/github/hyuwah/draggableview/overlay/OverlayService.kt)\n\n\n## Related Article\n\n* [Implementasi DraggableView di Android (Bahasa)](https://medium.com/@hyuwah/implementasi-draggable-view-di-android-eb84e50fbba9)\n\n## License\n**DraggableView** is available under the MIT license. See the [LICENSE](https://github.com/hyuwah/DraggableView/blob/master/LICENSE) file for more info.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyuwah%2Fdraggableview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhyuwah%2Fdraggableview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyuwah%2Fdraggableview/lists"}