Last active
September 27, 2020 11:01
-
-
Save usausa/619b00b94bce0d01e8cba28e8eafa38d to your computer and use it in GitHub Desktop.
Xamarin.Forms custom side menu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8" ?> | |
<ContentPage | |
x:Class="SideMenuTest.MainPage" | |
xmlns="http://xamarin.com/schemas/2014/forms" | |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> | |
<AbsoluteLayout> | |
<StackLayout | |
AbsoluteLayout.LayoutBounds="0,0,1,1" | |
AbsoluteLayout.LayoutFlags="All" | |
Background="Blue"> | |
<Label | |
FontSize="Large" | |
Text="12345678901234567890" | |
TextColor="White" /> | |
</StackLayout> | |
<BoxView | |
AbsoluteLayout.LayoutBounds="0,0,AutoSize,1" | |
AbsoluteLayout.LayoutFlags="XProportional,YProportional,HeightProportional" | |
Opacity="0" | |
WidthRequest="16"> | |
<BoxView.GestureRecognizers> | |
<PanGestureRecognizer PanUpdated="Anchor_OnPanUpdated" /> | |
</BoxView.GestureRecognizers> | |
</BoxView> | |
<StackLayout | |
x:Name="SideMenu" | |
AbsoluteLayout.LayoutBounds="-240,0,AutoSize,1" | |
AbsoluteLayout.LayoutFlags="YProportional,HeightProportional" | |
Background="Green" | |
WidthRequest="240"> | |
<StackLayout.GestureRecognizers> | |
<PanGestureRecognizer PanUpdated="SideMenu_OnPanUpdated" /> | |
</StackLayout.GestureRecognizers> | |
</StackLayout> | |
</AbsoluteLayout> | |
</ContentPage> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace SideMenuTest | |
{ | |
using System; | |
using Xamarin.Forms; | |
public partial class MainPage | |
{ | |
public MainPage() | |
{ | |
InitializeComponent(); | |
} | |
private bool showSideMenu; | |
private double lastPosition; | |
private void Anchor_OnPanUpdated(object sender, PanUpdatedEventArgs e) | |
{ | |
if (e.StatusType == GestureStatus.Started) | |
{ | |
ViewExtensions.CancelAnimations(SideMenu); | |
var rect = AbsoluteLayout.GetLayoutBounds(SideMenu); | |
showSideMenu = rect.X > -SideMenu.Width; | |
lastPosition = rect.X; | |
} | |
else if (e.StatusType == GestureStatus.Running) | |
{ | |
var rect = AbsoluteLayout.GetLayoutBounds(SideMenu); | |
rect.X = Math.Max(Math.Min(0, e.TotalX - SideMenu.Width), -SideMenu.Width); | |
AbsoluteLayout.SetLayoutBounds(SideMenu, rect); | |
if (rect.X > lastPosition) | |
{ | |
showSideMenu = true; | |
} | |
else if (rect.X < lastPosition) | |
{ | |
showSideMenu = false; | |
} | |
lastPosition = rect.X; | |
} | |
else if (e.StatusType == GestureStatus.Completed) | |
{ | |
var rect = AbsoluteLayout.GetLayoutBounds(SideMenu); | |
var pos = showSideMenu ? 0 : -SideMenu.Width; | |
var length = (uint)(250 * Math.Abs(pos - rect.X) / SideMenu.Width); | |
SideMenu.Animate("Slide", x => | |
{ | |
rect.X = x; | |
AbsoluteLayout.SetLayoutBounds(SideMenu, rect); | |
}, rect.X, pos, length: length); | |
} | |
} | |
private void SideMenu_OnPanUpdated(object sender, PanUpdatedEventArgs e) | |
{ | |
if (e.StatusType == GestureStatus.Started) | |
{ | |
ViewExtensions.CancelAnimations(SideMenu); | |
var rect = AbsoluteLayout.GetLayoutBounds(SideMenu); | |
showSideMenu = rect.X > -SideMenu.Width; | |
lastPosition = rect.X; | |
} | |
else if (e.StatusType == GestureStatus.Running) | |
{ | |
var rect = AbsoluteLayout.GetLayoutBounds(SideMenu); | |
rect.X = Math.Max(Math.Min(0, rect.X + e.TotalX), -SideMenu.Width); | |
AbsoluteLayout.SetLayoutBounds(SideMenu, rect); | |
if (rect.X > lastPosition) | |
{ | |
showSideMenu = true; | |
} | |
else if (rect.X < lastPosition) | |
{ | |
showSideMenu = false; | |
} | |
lastPosition = rect.X; | |
} | |
else if (e.StatusType == GestureStatus.Completed) | |
{ | |
var rect = AbsoluteLayout.GetLayoutBounds(SideMenu); | |
var pos = showSideMenu ? 0 : -SideMenu.Width; | |
var length = (uint)(250 * Math.Abs(pos - rect.X) / SideMenu.Width); | |
SideMenu.Animate("Slide", x => | |
{ | |
rect.X = x; | |
AbsoluteLayout.SetLayoutBounds(SideMenu, rect); | |
}, rect.X, pos, length: length); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment