Skip to content
Simple Xamarin.Forms radial menu without renderers
Branch: master
Clone or download
Latest commit 88e1912 Jan 27, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Xamarin.Forms.RadialMenu.AndroidCore Smart Boundaries Containment Logic Jan 25, 2019
Xamarin.Forms.RadialMenu.iOSCore
Xamarin.Forms.RadialMenu Updated nuspec Jan 27, 2019
images images_2 Aug 17, 2018
.gitignore
LICENSE Initial commit Aug 15, 2018
README.md
Xamarin.Forms.RadialMenu.sln

README.md

Xamarin.Forms-RadialMenu

Xamarin.Forms simple radial menu without renderers. **Android, iOS and UWP Supported**

Motivation

  • Create a reusable RadialMenu without relying on any CustomRenderer

Installation

Install NuGet package: Xamarin.Forms.RadialMenu or download repo and compile it manually so you can reference it from your target project :D

Usage

1.- Just reference it in your View and set MenuItemsSource property:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"   
             <!-- REFERENCE XAML NAMESPACE-->
             xmlns:radial="clr-namespace:Xamarin.Forms.RadialMenu;assembly=Xamarin.Forms.RadialMenu"   
             x:Class="Xamarin.Forms.RadialMenu.MainPage">

    <Grid>   <!-- IT IS RECOMMENDED TO USE WITHIN A GRID SO IT TAKES ADVANTAGE OF GRID OVERLAPPING-->
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="40"></RowDefinition>
        </Grid.RowDefinitions>
          
              <radial:RadialMenu MenuItemsSource="{Binding MenuItems}" Grid.Row="0"
                          HorizontalOptions="Fill" 
                          VerticalOptions="Fill"
                          MainMenuCloseButtonImageSource="close_circle.png"    <!-- CLOSE IMAGE-->
                          OuterCircleImageSource="outer_circle.png"             <!-- OUTER CIRCLE IMAGE-->
                          MainMenuImageSource="menu_circle.png"                 <!-- MAIN MENU IMAGE-->
                          x:Name="Menu">
                          
                           <!--HORIZONTAL/VERTICAL OPTIONS ARE DIFFERENT FOR EACH PLATFORM -->
                            <!--For Android use Center for Horizontal and Vertical -->
                            <!--For iOS use Fill for Horizontal and Vertical -->
                            <!--THIS ENSURES CLICK EVENTS PROPAGATES ONLY IN MENU AND NOT THROUGH ENTIRE GRID -->
                            
                          <radial:RadialMenu.HorizontalOptions>
                              <OnPlatform x:TypeArguments="LayoutOptions">    
                                  <On Platform="Android" Value="Center"/>
                                  <On Platform="iOS" Value="Fill"/>
                              </OnPlatform>
                          </radial:RadialMenu.HorizontalOptions>
                           <radial:RadialMenu.VerticalOptions>
                               <OnPlatform x:TypeArguments="LayoutOptions">    
                                  <On Platform="Android" Value="Center"/>
                                  <On Platform="iOS" Value="Fill"/>
                              </OnPlatform>
                          </radial:RadialMenu.VerticalOptions>
                </radial:RadialMenu>
              <Label x:Name="Notifier" Grid.Row="1" HorizontalTextAlignment="Center"></Label>

        <!--ON ANDROID MAKE SURE IMAGES EXISTS IN RESOURCES FOLDER BEFORE RUNNING APP.OTHERWISE IT MAY CRASH-->
         
........
 

2.- And your ViewModel/Codebehind code will look similar to:

//Add controls to Menu collection
            vm = new MainMenuViewModel();
            BindingContext = vm;
            vm.MenuItems = new ObservableCollection<RadialMenuItem>()
            {
                new RadialMenuItem()
                {
                    Source = "menu_paint.png",
                    WidthRequest = 38,
                    HeightRequest = 38,
                    VerticalOptions = LayoutOptions.Center,
                    HorizontalOptions = LayoutOptions.Center,
                    Location = Enumerations.Enumerations.RadialMenuLocation.N
                }
            };
            vm.MenuItems.Add(new RadialMenuItem()
            {
                Source = "menu_lorry.png",
                WidthRequest = 38,
                HeightRequest = 38,
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
                Location = Enumerations.Enumerations.RadialMenuLocation.Ne
            });
 ........

Events

  Menu.ItemTapped += async (sender, location) =>
            {
                  var textLocation = location.ToString();
            };

Enumerations

Project contain an enumeration which is used to set each menu item location within RadialMenu. By default it follows clockwise to animate items when showing(First North then North-East and so on).

        public enum RadialMenuLocation
        {
            N = 0,//North
            Ne = 1,//North-East
            Nw = 7,//North-West
            S = 4,//South
            Se = 3,//South-East
            Sw = 5,//South-West
            W = 6,//West
            E = 2//East
        }
        

Image of Yaktocat

How it looks

Alt Text

Adding Custom Content

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.

    public virtual void Draw()
      {
          var itemGrid = new Grid();
          if (Source != null)
          {
              itemGrid.Children.Add(new Image() { Source=this.Source});
              this.Content = itemGrid;
          }
      }

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.

public class CustomizedItem:RadialMenuItem
  {
      public override void Draw()
      {
          var itemGrid = new StackLayout(){Spacing=0};
          if (Source != null)
          {
             
              itemGrid.Children.Add(new Image(){Source=Source});
              var label = new Label() {FontSize=11,
                VerticalOptions = LayoutOptions.End,TextColor=Color.White,
                HorizontalTextAlignment=TextAlignment.Center,
                Text= Title, 
                Margin=new Thickness(0,1,0,0)};
              itemGrid.Children.Add(label);
              Content = itemGrid;
          }
      }
  }
  
  
  vm.MenuItems = new ObservableCollection<RadialMenuItem>()
          {
              new CustomizedItem()
              {
                  Source = "menu_paint.png",
                  WidthRequest = 38,
                  HeightRequest = 38,
                  VerticalOptions = LayoutOptions.Center,
                  HorizontalOptions = LayoutOptions.Center,
                  Location = Enumerations.Enumerations.RadialMenuLocation.N,Title="North"
              }
          };

Image of Yaktocat

Adding Custom Renderers (Optional)

Currently 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.

You can find the Android renderer here:

You can find the iOS renderer here:

Call Abstractions.Init() on each platform

Alt Text

Missing Features

  • Add Nested lists to each RadialMenuItem
  • Add different animations to show radial menu and RadialMenuItems
  • Draggable renderer for UWP

Special Thanks


Happy coding! 🐫 💥

You can’t perform that action at this time.