{"id":13713114,"url":"https://github.com/arqueror/Xamarin.Forms-RadialMenu","last_synced_at":"2025-05-06T23:30:37.957Z","repository":{"id":74728508,"uuid":"144794789","full_name":"arqueror/Xamarin.Forms-RadialMenu","owner":"arqueror","description":"Simple Xamarin.Forms/.Net MAUI radial menu without renderers","archived":false,"fork":false,"pushed_at":"2022-11-07T19:28:45.000Z","size":1703,"stargazers_count":125,"open_issues_count":1,"forks_count":17,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-19T17:08:49.684Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","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/arqueror.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}},"created_at":"2018-08-15T02:18:56.000Z","updated_at":"2025-01-15T15:28:27.000Z","dependencies_parsed_at":"2023-10-20T17:42:23.179Z","dependency_job_id":null,"html_url":"https://github.com/arqueror/Xamarin.Forms-RadialMenu","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arqueror%2FXamarin.Forms-RadialMenu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arqueror%2FXamarin.Forms-RadialMenu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arqueror%2FXamarin.Forms-RadialMenu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arqueror%2FXamarin.Forms-RadialMenu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arqueror","download_url":"https://codeload.github.com/arqueror/Xamarin.Forms-RadialMenu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252787171,"owners_count":21804211,"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","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":[],"created_at":"2024-08-02T23:01:27.763Z","updated_at":"2025-05-06T23:30:36.270Z","avatar_url":"https://github.com/arqueror.png","language":"C#","funding_links":["https://www.buymeacoffee.com/jOUwyzl"],"categories":["UI"],"sub_categories":[],"readme":"# Xamarin.Forms-RadialMenu \n\u003cimg src=\"https://api.nuget.org/v3-flatcontainer/xamarin.forms.radialmenu/2.0.2/icon\" width=\"144\"\u003e     \nXamarin.Forms simple radial menu without renderers. **Android, iOS and UWP Supported**\n\n# .NET MAUI Support (In Progress)\nCurrently working on .Net MAUI migration (maui_migration branch)\n \n\n# Motivation\n  - Create a reusable RadialMenu without relying on any CustomRenderer\n \n \n# Installation\nInstall NuGet package: **Xamarin.Forms.RadialMenu**\nor download repo and compile it manually so you can reference it from your target project :D\n\n\n# Usage\n**1.- Just reference it in your View and set MenuItemsSource property:**\n```xml\n\u003cContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"   \n             \u003c!-- REFERENCE XAML NAMESPACE--\u003e\n             xmlns:radial=\"clr-namespace:Xamarin.Forms.RadialMenu;assembly=Xamarin.Forms.RadialMenu\"   \n             x:Class=\"Xamarin.Forms.RadialMenu.MainPage\"\u003e\n\n    \u003cGrid\u003e   \u003c!-- IT IS RECOMMENDED TO USE WITHIN A GRID SO IT TAKES ADVANTAGE OF GRID OVERLAPPING--\u003e\n        \u003cGrid.RowDefinitions\u003e\n            \u003cRowDefinition\u003e\u003c/RowDefinition\u003e\n            \u003cRowDefinition Height=\"40\"\u003e\u003c/RowDefinition\u003e\n        \u003c/Grid.RowDefinitions\u003e\n           \u003clocal:RadialMenu BackButtonImageSource=\"back_circle.png\"         \u003c!-- CHILD MENU BACK BUTTON IMAGE--\u003e\n                          OuterCircleImageSource=\"outer_circle.png\"          \u003c!-- OUTER CIRCLE IMAGE--\u003e\n                          MainMenuCloseButtonImageSource=\"close_circle.png\"  \u003c!-- CLOSE IMAGE--\u003e\n                          MainMenuImageSource=\"menu_circle.png\"              \u003c!-- MAIN MENU IMAGE--\u003e\n                          MenuItemsSource=\"{Binding MenuItems}\" \n                          Grid.Row=\"0\" x:Name=\"Menu\" \n                          CloseMenuWhenChildTapped=\"false\"\n                          ChildGrowAnimationDuration=\"400\"\n                          ChildShrinkAnimationDuration=\"400\"\n                          MenuOpenAnimationDuration=\"800\"\n                          MenuCloseAnimationDuration=\"800\"\n                          IsMenuSandboxEnabled=\"False\"\n                          MenuItemAppearingDuration=\"100\"\n                          MenuItemHidingDuration=\"80\"\n                          ChildGrowEasing=\"{x:Static Easing.SpringOut}\"\n                          ChildShrinkEasing=\"{x:Static Easing.CubicOut}\"\n                          MenuOpenEasing=\"{x:Static Easing.BounceIn}\"\n                          MenuCloseEasing=\"{x:Static Easing.BounceOut}\"\n                          IsShadowVisible=\"True\"\u003e\n                          \n                           \u003c!--HORIZONTAL/VERTICAL OPTIONS ARE DIFFERENT FOR EACH PLATFORM --\u003e\n                            \u003c!--For Android use Center for Horizontal and Vertical --\u003e\n                            \u003c!--For iOS use Fill for Horizontal and Vertical --\u003e\n                            \u003c!--THIS ENSURES CLICK EVENTS PROPAGATES ONLY IN MENU AND NOT THROUGH ENTIRE GRID --\u003e\n                            \n                           \u003clocal:RadialMenu.HorizontalOptions\u003e\n                            \u003cOnPlatform x:TypeArguments=\"LayoutOptions\"\u003e\n                                      \u003cOn Platform=\"Android\" Value=\"Center\" /\u003e\n                                      \u003cOn Platform=\"iOS\" Value=\"Fill\" /\u003e\n                                      \u003cOn Platform=\"UWP\" Value=\"Center\" /\u003e\n                                  \u003c/OnPlatform\u003e\n                              \u003c/local:RadialMenu.HorizontalOptions\u003e\n                              \u003clocal:RadialMenu.VerticalOptions\u003e\n                                  \u003cOnPlatform x:TypeArguments=\"LayoutOptions\"\u003e\n                                      \u003cOn Platform=\"Android\" Value=\"Center\" /\u003e\n                                      \u003cOn Platform=\"iOS\" Value=\"Fill\" /\u003e\n                                      \u003cOn Platform=\"UWP\" Value=\"Center\" /\u003e\n                                  \u003c/OnPlatform\u003e\n                            \u003c/local:RadialMenu.VerticalOptions\u003e\n                \u003c/local:RadialMenu\u003e\n                \u003cLabel x:Name=\"Notifier\" Grid.Row=\"1\" HorizontalTextAlignment=\"Center\"\u003e\u003c/Label\u003e\n\n        \u003c!--ON ANDROID MAKE SURE IMAGES EXISTS IN RESOURCES FOLDER BEFORE RUNNING APP.OTHERWISE IT MAY CRASH--\u003e\n         \n........\n \n  ```  \n    \n    \n**2.- And your ViewModel/Codebehind code will look similar to:**\n```C#\n            //Add items at initialization. Otherwise items won't show\n            vm = new MainMenuViewModel();\n            BindingContext = vm;\n           vm.MenuItems = new ObservableCollection\u003cRadialMenuItem\u003e()\n            {\n                new CustomizedItem()\n                {\n                    AppearingOrder = 0,\n                    Source = \"menu_paint.png\",\n                    WidthRequest = 38,\n                    HeightRequest = 38,\n                    VerticalOptions = LayoutOptions.Center,\n                    HorizontalOptions = LayoutOptions.Center,\n                    Location = Enumerations.Enumerations.RadialMenuLocation.N,Title=\"North\",\n                    ChildItems=new ObservableCollection\u003cRadialMenuItem\u003e()\n                    {\n\n                            new RadialMenuItem()\n                            {\n                                Source = \"menu_lorry.png\",\n                                WidthRequest = 38,\n                                HeightRequest = 38,\n                                VerticalOptions = LayoutOptions.Center,\n                                HorizontalOptions = LayoutOptions.Center,\n                                Location = Enumerations.Enumerations.RadialMenuLocation.N\n\n                            },\n                        new RadialMenuItem()\n                        {\n                            Source = \"menu_lorry.png\",\n                            WidthRequest = 38,\n                            HeightRequest = 38,\n                            VerticalOptions = LayoutOptions.Center,\n                            HorizontalOptions = LayoutOptions.Center,\n                            Location = Enumerations.Enumerations.RadialMenuLocation.Ne\n                        }, new RadialMenuItem()\n                        {\n                            Source = \"menu_factory.png\",\n                            WidthRequest = 38,\n                            HeightRequest = 38,\n                            VerticalOptions = LayoutOptions.Center,\n                            HorizontalOptions = LayoutOptions.Center,\n                            Location = Enumerations.Enumerations.RadialMenuLocation.E\n\n                        },\n\n                    }\n                },\n            \n            new CustomizedItem()\n            {\n                AppearingOrder = 0,\n                Source = \"menu_cow.png\",\n                WidthRequest = 38,\n                HeightRequest = 38,\n                VerticalOptions = LayoutOptions.Center,\n                HorizontalOptions = LayoutOptions.Center,\n                Location = Enumerations.Enumerations.RadialMenuLocation.Se,\n                Title = \"SE\"\n            },\n            new RadialMenuItem()\n            {\n                AppearingOrder = 0,\n                Source = \"menu_award.png\",\n                WidthRequest = 38,\n                HeightRequest = 38,\n                VerticalOptions = LayoutOptions.Center,\n                HorizontalOptions = LayoutOptions.Center,\n                Location = Enumerations.Enumerations.RadialMenuLocation.Sw\n            }};\n\n```\n## Properties\n            //Animations**\n            ChildShrinkEasing\n            ChildGrowEasing\n            MenuOpenEasing \n            MenuCloseEasing \n            //*************//\n            \n            BackButtonImageSource               //Child menu back button image\n            OuterCircleImageSource              //Outer menu circle backg image   \n            MainMenuCloseButtonImageSource      //Main Opened menu close button image\n            MainMenuImageSource                 //Closed menu button image\n            MenuItemsSource                     //Menu items\n            CloseMenuWhenChildTapped            //Trigger close logic when a child menu item is tapped. Otherwise triggers back   \n            ChildGrowAnimationDuration=\"600\"    //Child menu easing animation duration (Open)\n            ChildShrinkAnimationDuration=\"600\"  //Child menu shrinking animation duration (Closing)\n            MenuOpenAnimationDuration=\"100\"     //Main menu open animation duration\n            MenuCloseAnimationDuration=\"100\"    //Main menu close animation duration \n            IsShadowVisible=\"True\"              //Enable/Disable background shadow. For android only Api\u003e=21 supported\n\n\n## Events\n```C#\n  Menu.ItemTapped += async (sender, location) =\u003e\n            {\n                  var textLocation = location.ToString();\n            };\n            \n   Menu.ChildItemTapped += async (sender, child) =\u003e\n            {\n                Notifier.Text = $\"Parent:{child.Parent.Location.ToString()} Child:{child.ItemTapped.ToString()}\";\n                await Task.Delay(5000);\n                Notifier.Text = \"\";\n\n            };\n            \n    Menu.MenuClosed += async (s, a) =\u003e\n            {\n               \n            };\n            \n    Menu.MenuOpened += async (s, a) =\u003e\n            {\n               \n            };\n\n```\n\n## Enumerations\nProject contain an enumeration which is used to set each menu item location within RadialMenu. \nBy default it follows clockwise to animate items when showing(First North then North-East and so on).\n```C# sh\n        public enum RadialMenuLocation\n        {\n            N = 0,//North\n            Ne = 1,//North-East\n            Nw = 7,//North-West\n            S = 4,//South\n            Se = 3,//South-East\n            Sw = 5,//South-West\n            W = 6,//West\n            E = 2//East\n        }\n        \n```\n ![Image of Yaktocat](https://image.shutterstock.com/image-vector/wind-rose-cardinal-points-star-260nw-1011439111.jpg)\n\n# How it looks\n![Alt Text](https://github.com/arqueror/Xamarin.Forms-RadialMenu/blob/master/images/RadialMenu.gif)\n  \n  \n  # Adding Custom Content\n  Items relies on a base class called **RadialMenuItem**, which exposes a virtual method called **Draw**. By default this method is in charge of drawing each item in the position we manually set in the beginning.\n  ```C#\n      public virtual void Draw()\n        {\n            var itemGrid = new Grid();\n            if (Source != null)\n            {\n                itemGrid.Children.Add(new Image() { Source=this.Source});\n                this.Content = itemGrid;\n            }\n        }\n  ```\n  In case you want to add other items than JUST Images you can!. Just create a class that inherits from **RadialMenuItem**, override **Draw()** and build your own element (**just make sure to use Labels and Images since tapped event behaves nicely this way**). After this just use it normally when creating the menu items list in your VM.\n  ```C#\n  public class CustomizedItem:RadialMenuItem\n    {\n        public override void Draw()\n        {\n            var itemGrid = new StackLayout(){Spacing=0};\n            if (Source != null)\n            {\n               \n                itemGrid.Children.Add(new Image(){Source=Source});\n                var label = new Label() {FontSize=11,\n                  VerticalOptions = LayoutOptions.End,TextColor=Color.White,\n                  HorizontalTextAlignment=TextAlignment.Center,\n                  Text= Title, \n                  Margin=new Thickness(0,1,0,0)};\n                itemGrid.Children.Add(label);\n                Content = itemGrid;\n            }\n        }\n    }\n    \n    \n    vm.MenuItems = new ObservableCollection\u003cRadialMenuItem\u003e()\n            {\n                new CustomizedItem()\n                {\n                    Source = \"menu_paint.png\",\n                    WidthRequest = 38,\n                    HeightRequest = 38,\n                    VerticalOptions = LayoutOptions.Center,\n                    HorizontalOptions = LayoutOptions.Center,\n                    Location = Enumerations.Enumerations.RadialMenuLocation.N,Title=\"North\"\n                }\n            };\n  ```\n  ![Image of Yaktocat](https://arqueror.blob.core.windows.net/publicfiles/RadialMenu_03.PNG?raw=false)\n  \n# Adding Custom Renderers (Optional)\nCurrently custom rendererers are only available for **Android and iOS (UWP coming soon)** and they add **Dragging** capability to your RadialMenu and it is completely optional for you to use it or not.\n\nYou can find the **Android** renderer here: \n\n- https://github.com/arqueror/Xamarin.Forms-RadialMenu/blob/master/Xamarin.Forms.RadialMenu.AndroidCore/DraggableViewRenderer.cs\n- NuGet: Xamarin.Forms.RadialMenu.AndroidCore\n\n\nYou can find the **iOS** renderer here:\n\n- https://github.com/arqueror/Xamarin.Forms-RadialMenu/blob/master/Xamarin.Forms.RadialMenu.iOSCore/DraggableViewRenderer.cs\n- NuGet: Xamarin.Forms.RadialMenu.iOSCore\n\n\n**Call Abstractions.Init()** on each platform\n\n# Missing Features\n- **Draggable renderer for UWP**\n\n\n# Special Thanks\n - Alan Beech (https://github.com/alanbeech) for the base code used for this repo.\n - CrossGeeks (https://github.com/CrossGeeks) for the Drag renderer base code.\n\u003cbr/\u003e\n\n# Did you like it?\n\n\u003ca href=\"https://www.buymeacoffee.com/jOUwyzl\" target=\"_blank\"\u003e\u003cimg src=\"https://www.buymeacoffee.com/assets/img/custom_images/purple_img.png\" alt=\"Buy Me A Coffee\" style=\"height: auto !important;width: auto !important;\" \u003e\u003c/a\u003e\n\nYour caffeine helps me a lot :sparkles:\n\n**Happy coding! :sparkles: :camel: :boom:**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farqueror%2FXamarin.Forms-RadialMenu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farqueror%2FXamarin.Forms-RadialMenu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farqueror%2FXamarin.Forms-RadialMenu/lists"}