GithubHelp home page GithubHelp logo

hefujie1988 / xamarin.forms-radialmenu Goto Github PK

View Code? Open in Web Editor NEW

This project forked from arqueror/xamarin.forms-radialmenu

0.0 0.0 0.0 777 KB

Simple Xamarin.Forms radial menu without renderers

License: MIT License

C# 100.00%

xamarin.forms-radialmenu's Introduction

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>
           <local:RadialMenu BackButtonImageSource="back_circle.png"         <!-- CHILD MENU BACK BUTTON IMAGE-->
                          OuterCircleImageSource="outer_circle.png"          <!-- OUTER CIRCLE IMAGE-->
                          MainMenuCloseButtonImageSource="close_circle.png"  <!-- CLOSE IMAGE-->
                          MainMenuImageSource="menu_circle.png"              <!-- MAIN MENU IMAGE-->
                          MenuItemsSource="{Binding MenuItems}" 
                          Grid.Row="0" x:Name="Menu" 
                          CloseMenuWhenChildTapped="false"
                          ChildGrowAnimationDuration="400"
                          ChildShrinkAnimationDuration="400"
                          MenuOpenAnimationDuration="800"
                          MenuCloseAnimationDuration="800"
                          IsMenuSandboxEnabled="False"
                          MenuItemAppearingDuration="100"
                          MenuItemHidingDuration="80"
                          ChildGrowEasing="{x:Static Easing.SpringOut}"
                          ChildShrinkEasing="{x:Static Easing.CubicOut}"
                          MenuOpenEasing="{x:Static Easing.BounceIn}"
                          MenuCloseEasing="{x:Static Easing.BounceOut}"
                          IsShadowVisible="True">
                          
                           <!--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 -->
                            
                           <local:RadialMenu.HorizontalOptions>
                            <OnPlatform x:TypeArguments="LayoutOptions">
                                      <On Platform="Android" Value="Center" />
                                      <On Platform="iOS" Value="Fill" />
                                      <On Platform="UWP" Value="Center" />
                                  </OnPlatform>
                              </local:RadialMenu.HorizontalOptions>
                              <local:RadialMenu.VerticalOptions>
                                  <OnPlatform x:TypeArguments="LayoutOptions">
                                      <On Platform="Android" Value="Center" />
                                      <On Platform="iOS" Value="Fill" />
                                      <On Platform="UWP" Value="Center" />
                                  </OnPlatform>
                            </local:RadialMenu.VerticalOptions>
                </local: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 items at initialization. Otherwise items won't show
            vm = new MainMenuViewModel();
            BindingContext = vm;
           vm.MenuItems = new ObservableCollection<RadialMenuItem>()
            {
                new CustomizedItem()
                {
                    AppearingOrder = 0,
                    Source = "menu_paint.png",
                    WidthRequest = 38,
                    HeightRequest = 38,
                    VerticalOptions = LayoutOptions.Center,
                    HorizontalOptions = LayoutOptions.Center,
                    Location = Enumerations.Enumerations.RadialMenuLocation.N,Title="North",
                    ChildItems=new ObservableCollection<RadialMenuItem>()
                    {

                            new RadialMenuItem()
                            {
                                Source = "menu_lorry.png",
                                WidthRequest = 38,
                                HeightRequest = 38,
                                VerticalOptions = LayoutOptions.Center,
                                HorizontalOptions = LayoutOptions.Center,
                                Location = Enumerations.Enumerations.RadialMenuLocation.N

                            },
                        new RadialMenuItem()
                        {
                            Source = "menu_lorry.png",
                            WidthRequest = 38,
                            HeightRequest = 38,
                            VerticalOptions = LayoutOptions.Center,
                            HorizontalOptions = LayoutOptions.Center,
                            Location = Enumerations.Enumerations.RadialMenuLocation.Ne
                        }, new RadialMenuItem()
                        {
                            Source = "menu_factory.png",
                            WidthRequest = 38,
                            HeightRequest = 38,
                            VerticalOptions = LayoutOptions.Center,
                            HorizontalOptions = LayoutOptions.Center,
                            Location = Enumerations.Enumerations.RadialMenuLocation.E

                        },

                    }
                },
            
            new CustomizedItem()
            {
                AppearingOrder = 0,
                Source = "menu_cow.png",
                WidthRequest = 38,
                HeightRequest = 38,
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
                Location = Enumerations.Enumerations.RadialMenuLocation.Se,
                Title = "SE"
            },
            new RadialMenuItem()
            {
                AppearingOrder = 0,
                Source = "menu_award.png",
                WidthRequest = 38,
                HeightRequest = 38,
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
                Location = Enumerations.Enumerations.RadialMenuLocation.Sw
            }};

Properties

        //Animations**
        ChildShrinkEasing
        ChildGrowEasing
        MenuOpenEasing 
        MenuCloseEasing 
        //*************//
        
        BackButtonImageSource               //Child menu back button image
        OuterCircleImageSource              //Outer menu circle backg image   
        MainMenuCloseButtonImageSource      //Main Opened menu close button image
        MainMenuImageSource                 //Closed menu button image
        MenuItemsSource                     //Menu items
        CloseMenuWhenChildTapped            //Trigger close logic when a child menu item is tapped. Otherwise triggers back   
        ChildGrowAnimationDuration="600"    //Child menu easing animation duration (Open)
        ChildShrinkAnimationDuration="600"  //Child menu shrinking animation duration (Closing)
        MenuOpenAnimationDuration="100"     //Main menu open animation duration
        MenuCloseAnimationDuration="100"    //Main menu close animation duration 
        IsShadowVisible="True"              //Enable/Disable background shadow. For android only Api>=21 supported

Events

  Menu.ItemTapped += async (sender, location) =>
            {
                  var textLocation = location.ToString();
            };
            
   Menu.ChildItemTapped += async (sender, child) =>
            {
                Notifier.Text = $"Parent:{child.Parent.Location.ToString()} Child:{child.ItemTapped.ToString()}";
                await Task.Delay(5000);
                Notifier.Text = "";

            };

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

  • Draggable renderer for UWP

Special Thanks


Did you like it?

Buy Me A Coffee

Your caffeine helps me a lot โœจ

Happy coding! โœจ ๐Ÿซ ๐Ÿ’ฅ

xamarin.forms-radialmenu's People

Contributors

arqueror avatar gamerz0mbie66 avatar dependabot[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.