{"id":26865735,"url":"https://github.com/anasselkadii/reactflowcanvasview-","last_synced_at":"2026-04-11T08:04:06.991Z","repository":{"id":285090928,"uuid":"957039427","full_name":"anasselkadii/ReactFlowCanvasView-","owner":"anasselkadii","description":"A native Android custom View for creating interactive, node-based flow charts and diagrams with panning, zooming, connections, and customization. Mimics concepts from libraries like React Flow/n8n                                                DM on insta @alkadianass","archived":false,"fork":false,"pushed_at":"2025-11-19T16:46:45.000Z","size":6217,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-19T18:22:24.728Z","etag":null,"topics":["anass-elkadi","android","androidstudio","canvas","java","kotlin","n8n-nodes","node-based","react-flow","workflow-automation"],"latest_commit_sha":null,"homepage":"","language":"Java","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/anasselkadii.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-29T12:07:37.000Z","updated_at":"2025-11-19T16:46:49.000Z","dependencies_parsed_at":"2025-03-31T04:26:25.742Z","dependency_job_id":null,"html_url":"https://github.com/anasselkadii/ReactFlowCanvasView-","commit_stats":null,"previous_names":["nasleceo/reactflowcanvasview-","anasselkadii/reactflowcanvasview-"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/anasselkadii/ReactFlowCanvasView-","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anasselkadii%2FReactFlowCanvasView-","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anasselkadii%2FReactFlowCanvasView-/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anasselkadii%2FReactFlowCanvasView-/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anasselkadii%2FReactFlowCanvasView-/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anasselkadii","download_url":"https://codeload.github.com/anasselkadii/ReactFlowCanvasView-/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anasselkadii%2FReactFlowCanvasView-/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31673068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-10T17:19:37.612Z","status":"online","status_checked_at":"2026-04-11T02:00:05.776Z","response_time":54,"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":["anass-elkadi","android","androidstudio","canvas","java","kotlin","n8n-nodes","node-based","react-flow","workflow-automation"],"created_at":"2025-03-31T04:23:29.423Z","updated_at":"2026-04-11T08:04:06.985Z","avatar_url":"https://github.com/anasselkadii.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ReactFlowCanvasView ✨ - Native Android Flow Chart UI\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) \u003c!-- Optional License Badge --\u003e\n\nA custom Android `View` written in Java that mimics the look and feel of popular node-based UI libraries like React Flow or n8n, allowing you to create interactive flow charts, diagrams, or workflow editors natively on Android.\n\n![ReactFlowCanvasView Screenshot/PNG](https://b.top4top.io/p_3375151zj1.jpg) \u003c!-- **\u003c\u003c\u003c REPLACE THIS WITH AN ACTUAL SCREENSHOT OR GIF!** --\u003e\n![ReactFlowCanvasView Screenshot/PNG](https://c.top4top.io/p_3375737wq2.jpg) \u003c!-- **\u003c\u003c\u003c REPLACE THIS WITH AN ACTUAL SCREENSHOT OR GIF!** --\u003e\n\n\n\nThis view provides a smooth, interactive canvas with panning, button-controlled zooming, node dragging, handle-based connections, and various customization options.\n\n---\n\n## 🚀 Features\n\n*   **Infinite Canvas:** Pan around freely using single-finger drag.\n*   **Button Zooming:** Dedicated buttons for smooth zooming in/out, centered on the view. (Pinch-to-zoom disabled by default).\n*   **Node Management:**\n    *   Add nodes programmatically with custom icons, labels, sizes, and backgrounds.\n    *   Support for different node shapes (Rectangle, Custom Drawable).\n    *   Drag and drop nodes to reposition them.\n*   **Connection System:**\n    *   Define input/output handles (connection points) on nodes.\n    *   Create connections by dragging from one handle to another valid handle.\n    *   Visual feedback (temporary line) during connection drawing.\n    *   \"Snap-to-handle\" connection finalization based on hit radius.\n*   **Edge Styling:**\n    *   Smooth, curved connection lines (Quadratic Bezier).\n    *   Optional arrowheads at the end of connections.\n    *   Optional dashed line effect for \"animated\" edges.\n*   **Customization API:**\n    *   Configure colors (grid, nodes, edges, handles, text, etc.).\n    *   Set sizes (nodes, text, arrowheads).\n    *   Adjust spacing (grid) and radii (nodes, handles).\n    *   Toggle features like arrowheads.\n*   **Event Listener:** Get notified when connections are successfully made or attempted.\n*   **Data Access:** Retrieve the current list of nodes and edges.\n*   **Theming:** Dark background with dotted grid by default, easily customizable.\n\n---\n\n## ⚙️ Setup \u0026 Integration\n\n1.  **Add the View:** Include `ReactFlowCanvasView` in your XML layout file:\n\n    ```xml\n    \u003c!-- res/layout/your_activity_layout.xml --\u003e\n    \u003cFrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        tools:context=\".YourActivity\"\u003e\n\n        \u003c!-- The Canvas View --\u003e\n        \u003ccom.anass.halak.reactflow.ReactFlowCanvasView\n            android:id=\"@+id/flowCanvasView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" /\u003e\n\n        \u003c!-- Add Buttons for Zooming, Adding Nodes, Execution etc. --\u003e\n        \u003cLinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"bottom|start\"\n            android:layout_margin=\"16dp\"\n            android:orientation=\"vertical\"\n            android:background=\"#80000000\"\n            android:padding=\"4dp\"\u003e\n            \u003cImageButton\n                android:id=\"@+id/zoomInButton\"\n                style=\"@style/Widget.AppCompat.Button.Borderless\"\n                android:layout_width=\"48dp\" android:layout_height=\"48dp\"\n                app:srcCompat=\"@android:drawable/ic_menu_add\"\n                app:tint=\"@android:color/white\" /\u003e\n            \u003cImageButton\n                android:id=\"@+id/zoomOutButton\"\n                 style=\"@style/Widget.AppCompat.Button.Borderless\"\n                android:layout_width=\"48dp\" android:layout_height=\"48dp\"\n                android:layout_marginTop=\"8dp\"\n                app:srcCompat=\"@android:drawable/ic_menu_delete\"\n                app:tint=\"@android:color/white\" /\u003e\n        \u003c/LinearLayout\u003e\n\n        \u003ccom.google.android.material.floatingactionbutton.FloatingActionButton\n            android:id=\"@+id/fabAddNode\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"bottom|end\"\n            android:layout_margin=\"16dp\"\n            app:srcCompat=\"@android:drawable/ic_input_add\" /\u003e\n\n         \u003cButton\n            android:id=\"@+id/executeButton\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"top|end\"\n            android:layout_margin=\"16dp\"\n            android:text=\"Execute\"/\u003e\n\n    \u003c/FrameLayout\u003e\n    ```\n\n2.  **Reference in Activity:** Get a reference to the view in your Activity's `onCreate`:\n\n    ```java\n    // In YourActivity.java\n    import com.anass.halak.reactflow.ReactFlowCanvasView;\n    // ... other imports\n\n    public class YourActivity extends AppCompatActivity {\n        private ReactFlowCanvasView flowCanvasView;\n        // ... references for buttons ...\n\n        @Override\n        protected void onCreate(Bundle savedInstanceState) {\n            super.onCreate(savedInstanceState);\n            setContentView(R.layout.your_activity_layout);\n\n            flowCanvasView = findViewById(R.id.flowCanvasView);\n            // ... find other buttons ...\n\n            // Setup button listeners and listener for the view\n            setupListeners();\n            applyInitialCustomizations(); // Optional\n        }\n\n        private void setupListeners() {\n            // ... (See Event Handling section below) ...\n        }\n\n        private void applyInitialCustomizations() {\n             // ... (See Customization section below) ...\n        }\n    }\n    ```\n\n---\n\n## 💡 Core Concepts (Data Classes)\n\nThe view relies on these simple data classes (defined as static inner classes or separate files):\n\n*   **`Node`**: Represents a visual block on the canvas. Contains `id`, `position` (center PointF), `size` (RectF width/height), `label`, `shape` (enum), `customDrawableResId` (for icon), `backgroundDrawableResId` (optional), and lists of `inputHandles` and `outputHandles`.\n*   **`Edge`**: Represents a connection line. Contains `id`, `sourceNodeId`, `sourceHandleId`, `targetNodeId`, `targetHandleId`, and a boolean `animated` flag.\n*   **`Handle`**: Represents an input or output connection point on a Node. Contains `id`, `nodeId`, `type` (enum INPUT/OUTPUT), `relativeOffset` (PointF from node top-left), `radius` (for hit detection), and calculated `worldPosition` (PointF).\n*   **`NodeShape`**: An `enum` to differentiate node types (`RECTANGLE`, `CUBE`, `CUSTOM_DRAWABLE`).\n\n---\n\n## 🛠️ Key Public Methods\n\n### Adding Nodes\n\n*   `addNode(PointF worldPosition, float width, float height, String label, @DrawableRes Integer iconResId, @DrawableRes Integer backgroundResId, int inputCount, int outputCount)`: The most flexible way to add a node with full control over its properties.\n*   `addNodeAtCenter(String label, @DrawableRes Integer iconResId, @DrawableRes Integer backgroundResId, int inputCount, int outputCount)`: Adds a node with specified properties at the current center of the view, using default DP sizes.\n*   `addNewCustomNodeWithOutputs(@DrawableRes int iconResId, String label, int outputCount)`: Convenience method similar to the FAB example, adds a node at the center with a specific background shape (`R.drawable.node_background_shape`) and specified output handles.\n*   `addNewCustomNode(@DrawableRes int iconResId, String label)`: Simplest way to add a custom node (like the FAB example) at the center with 1 input and 1 output handle.\n\n### Zooming\n\n*   `zoomIn()`: Zooms in by one step (`ZOOM_STEP`), keeping the view center stationary.\n*   `zoomOut()`: Zooms out by one step (`1.0f / ZOOM_STEP`), keeping the view center stationary.\n\n### Data Retrieval\n\n*   `List\u003cNode\u003e getNodes()`: Returns a *copy* of the current list of nodes.\n*   `List\u003cEdge\u003e getEdges()`: Returns a *copy* of the current list of edges.\n\n### Event Handling\n\n*   `setConnectionListener(ConnectionListener listener)`: Sets a listener to receive callbacks for connection events.\n\n---\n\n## 🎨 Customization (Parameters)\n\nYou can customize the appearance and behavior using various public `set...` methods. Call these after getting the view reference in your Activity.\n\n```java\n// In YourActivity.java\nflowCanvasView = findViewById(R.id.flowCanvasView);\n\n// Grid\nflowCanvasView.setGridSpacing(60f);\nflowCanvasView.setGridDotColor(Color.parseColor(\"#616161\"));\nflowCanvasView.setGridDotBaseRadius(1.0f);\n\n// Nodes (Defaults)\nflowCanvasView.setDefaultNodeBgColor(Color.parseColor(\"#37474F\")); // Bluish Gray\nflowCanvasView.setDefaultNodeBorderColor(Color.parseColor(\"#546E7A\"));\nflowCanvasView.setDefaultNodeTextColor(Color.parseColor(\"#ECEFF1\"));\nflowCanvasView.setDefaultNodeTextSize(14 * getResources().getDisplayMetrics().scaledDensity); // Set text size in SP\nflowCanvasView.setDefaultNodeCornerRadiusDp(8f);\n\n// Edges\nflowCanvasView.setEdgeColor(Color.parseColor(\"#78909C\"));\nflowCanvasView.setEdgeStrokeWidth(2.5f);\nflowCanvasView.setDrawArrowheads(true);\nflowCanvasView.setArrowheadSize(9f);\nflowCanvasView.setArrowheadColor(Color.parseColor(\"#78909C\"));\n\n// Handles\nflowCanvasView.setHandleInputColor(Color.parseColor(\"#81C784\")); // Lighter Green\nflowCanvasView.setHandleOutputColor(Color.parseColor(\"#64B5F6\")); // Lighter Blue\nflowCanvasView.setHandleBorderColor(Color.parseColor(\"#455A64\"));\nflowCanvasView.setHandleHitRadiusWorld(18f); // Slightly larger hit area\n\n// Temp Connection Line\nflowCanvasView.setTempConnectionColor(Color.parseColor(\"#FFCA28\")); // Amber\n\n🔌 Event Handling (Connection Listener)\n\nImplement the ConnectionListener interface in your Activity to react when edges are connected or connection attempts are made.\n\n// In YourActivity.java\n\nprivate void setupConnectionListener() {\n    flowCanvasView.setConnectionListener(new ReactFlowCanvasView.ConnectionListener() {\n        @Override\n        public void onEdgeConnected(ReactFlowCanvasView.Edge newEdge) {\n            // Called when a valid connection is successfully made\n            Log.i(TAG, \"Listener: Edge Connected - \" + newEdge.id);\n            // You could update your backend/data model here\n            Toast.makeText(YourActivity.this, \"Connected!\", Toast.LENGTH_SHORT).show();\n        }\n\n        @Override\n        public void onConnectionAttempted(ReactFlowCanvasView.Handle startHandle, @Nullable ReactFlowCanvasView.Handle endHandle) {\n            // Called when the user releases the finger after dragging from a handle\n            Log.d(TAG, \"Listener: Connection Attempted from \" + startHandle.id + \" to \" + (endHandle != null ? endHandle.id : \"null\"));\n            if (endHandle == null || !flowCanvasView.isValidConnectionTarget(startHandle, endHandle)) {\n                // Optional feedback for invalid/missed connection\n                Toast.makeText(YourActivity.this, \"Connection failed\", Toast.LENGTH_SHORT).show();\n            }\n        }\n    });\n}\n```\n⚠️ Limitations \u0026 Future Enhancements\n\nEdge Routing: Edges are currently drawn as simple quadratic Bezier curves. They do not automatically avoid overlapping nodes (requires complex pathfinding algorithms).\n\nAnimation: Edge animation is currently a static dashed line. True \"marching ants\" animation requires more complex drawing loop management. Pan/Zoom/Drag animations (fling, smooth zoom) are not implemented (requires OverScroller/ValueAnimator).\n\nComplex Node Layouts: The view draws basic shapes/icons/text. Creating nodes with intricate internal layouts (like form fields within a node) is not supported directly by this custom View.\n\nHandle Constraints: No built-in limit on how many edges can connect to a single handle. This logic would need to be added in createEdge.\n\nPerformance: Performance with a very large number of nodes/edges (\u003e hundreds) might degrade, as no view/data virtualization is implemented.\n\n🤝 Contributing\n\nContributions are welcome! Feel free to fork the repository, make improvements, and submit pull requests. Please adhere to standard coding practices and provide clear descriptions for your changes.\n\n📜 License\n\nThis project is licensed under the MIT License - see the LICENSE.md file for details (assuming you add one).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanasselkadii%2Freactflowcanvasview-","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanasselkadii%2Freactflowcanvasview-","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanasselkadii%2Freactflowcanvasview-/lists"}