├── FlyOutMenu.sln ├── FlyOutMenu ├── Assets │ └── AboutAssets.txt ├── FlyOutContainer.cs ├── FlyOutMenu.csproj ├── MainActivity.cs ├── Properties │ ├── AndroidManifest.xml │ └── AssemblyInfo.cs └── Resources │ ├── AboutResources.txt │ ├── Resource.designer.cs │ ├── drawable-xhdpi │ ├── action_menu.png │ ├── icon1.png │ └── iconelse.png │ ├── drawable │ ├── Icon.png │ ├── action_menu.png │ ├── icon1.png │ └── iconelse.png │ ├── layout │ ├── ContentLayout.axml │ ├── Main.axml │ └── MenuLayout.axml │ └── values │ └── Strings.xml └── README.md /FlyOutMenu.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlyOutMenu", "FlyOutMenu\FlyOutMenu.csproj", "{DC4A371A-1B94-4270-9EB6-F44A59153567}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {DC4A371A-1B94-4270-9EB6-F44A59153567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {DC4A371A-1B94-4270-9EB6-F44A59153567}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {DC4A371A-1B94-4270-9EB6-F44A59153567}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {DC4A371A-1B94-4270-9EB6-F44A59153567}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | StartupItem = FlyOutMenu\FlyOutMenu.csproj 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /FlyOutMenu/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with you package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); -------------------------------------------------------------------------------- /FlyOutMenu/FlyOutContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using Android.App; 7 | using Android.Content; 8 | using Android.OS; 9 | using Android.Runtime; 10 | using Android.Util; 11 | using Android.Views; 12 | using Android.Widget; 13 | using Android.Animation; 14 | using Android.Views.Animations; 15 | using Android.Graphics; 16 | using Android.Graphics.Drawables; 17 | 18 | namespace FlyOutMenu 19 | { 20 | public class FlyOutContainer : FrameLayout 21 | { 22 | bool opened; 23 | int contentOffsetX; 24 | ValueAnimator animator; 25 | ITimeInterpolator interpolator = new SmoothInterpolator (); 26 | VelocityTracker velocityTracker; 27 | bool stateBeforeTracking; 28 | bool isTracking; 29 | bool preTracking; 30 | int startX = -1, startY = -1; 31 | 32 | const int BezelArea = 30; //dip 33 | const int MaxOverlayAlpha = 170; 34 | const float ParallaxSpeedRatio = 0.25f; 35 | 36 | int touchSlop; 37 | int pagingTouchSlop; 38 | int minFlingVelocity; 39 | int maxFlingVelocity; 40 | 41 | GradientDrawable shadowDrawable; 42 | Paint overlayPaint; 43 | 44 | public FlyOutContainer (Context context) : 45 | base (context) 46 | { 47 | Initialize (); 48 | } 49 | 50 | public FlyOutContainer (Context context, IAttributeSet attrs) : 51 | base (context, attrs) 52 | { 53 | Initialize (); 54 | } 55 | 56 | public FlyOutContainer (Context context, IAttributeSet attrs, int defStyle) : 57 | base (context, attrs, defStyle) 58 | { 59 | Initialize (); 60 | } 61 | 62 | void Initialize () 63 | { 64 | var config = ViewConfiguration.Get (Context); 65 | this.touchSlop = config.ScaledTouchSlop; 66 | this.pagingTouchSlop = config.ScaledPagingTouchSlop; 67 | this.minFlingVelocity = config.ScaledMinimumFlingVelocity; 68 | this.maxFlingVelocity = config.ScaledMaximumFlingVelocity; 69 | const int BaseShadowColor = 0; 70 | var shadowColors = new[] { 71 | Color.Argb (0x90, BaseShadowColor, BaseShadowColor, BaseShadowColor).ToArgb (), 72 | Color.Argb (0, BaseShadowColor, BaseShadowColor, BaseShadowColor).ToArgb () 73 | }; 74 | this.shadowDrawable = new GradientDrawable (GradientDrawable.Orientation.RightLeft, 75 | shadowColors); 76 | this.overlayPaint = new Paint { 77 | Color = Color.Black, 78 | AntiAlias = true 79 | }; 80 | } 81 | 82 | View ContentView { 83 | get { 84 | return FindViewById (Resource.Id.FlyOutContent); 85 | } 86 | } 87 | 88 | View MenuView { 89 | get { 90 | return FindViewById (Resource.Id.FlyOutMenu); 91 | } 92 | } 93 | 94 | int MaxOffset { 95 | get { 96 | return MenuView.Width; 97 | } 98 | } 99 | 100 | public bool Opened { 101 | get { 102 | return opened; 103 | } 104 | set { 105 | SetOpened (value, animated: false); 106 | } 107 | } 108 | 109 | public bool AnimatedOpened { 110 | get { 111 | return opened; 112 | } 113 | set { 114 | SetOpened (value, animated: true); 115 | } 116 | } 117 | 118 | public void SetOpened (bool opened, bool animated = true) 119 | { 120 | this.opened = opened; 121 | if (!animated) 122 | SetNewOffset (opened ? MaxOffset : 0); 123 | else { 124 | if (animator != null) { 125 | animator.Cancel (); 126 | animator = null; 127 | } 128 | 129 | animator = ValueAnimator.OfInt (contentOffsetX, opened ? MaxOffset : 0); 130 | animator.SetInterpolator (interpolator); 131 | animator.SetDuration (Context.Resources.GetInteger (Android.Resource.Integer.ConfigMediumAnimTime)); 132 | animator.Update += (sender, e) => SetNewOffset ((int)e.Animation.AnimatedValue); 133 | animator.AnimationEnd += (sender, e) => { animator.RemoveAllListeners (); animator = null; }; 134 | animator.Start (); 135 | } 136 | } 137 | 138 | void SetNewOffset (int newOffset) 139 | { 140 | var oldOffset = contentOffsetX; 141 | contentOffsetX = Math.Min (Math.Max (0, newOffset), MaxOffset); 142 | ContentView.OffsetLeftAndRight (contentOffsetX - oldOffset); 143 | if (opened && contentOffsetX == 0) 144 | opened = false; 145 | else if (!opened && contentOffsetX == MaxOffset) 146 | opened = true; 147 | UpdateParallax (); 148 | Invalidate (); 149 | } 150 | 151 | void UpdateParallax () 152 | { 153 | var openness = ((float)(MaxOffset - contentOffsetX)) / MaxOffset; 154 | MenuView.OffsetLeftAndRight ((int)(-openness * MaxOffset * ParallaxSpeedRatio) - MenuView.Left); 155 | } 156 | 157 | public override bool OnInterceptTouchEvent (MotionEvent ev) 158 | { 159 | // Only accept single touch 160 | if (ev.PointerCount != 1) 161 | return false; 162 | 163 | return CaptureMovementCheck (ev); 164 | } 165 | 166 | public override bool OnTouchEvent (MotionEvent e) 167 | { 168 | if (e.Action == MotionEventActions.Down) { 169 | CaptureMovementCheck (e); 170 | return true; 171 | } 172 | if (!isTracking && !CaptureMovementCheck (e)) 173 | return true; 174 | 175 | if (e.Action != MotionEventActions.Move || MoveDirectionTest (e)) 176 | velocityTracker.AddMovement (e); 177 | 178 | if (e.Action == MotionEventActions.Move) { 179 | var x = e.HistorySize > 0 ? e.GetHistoricalX (0) : e.GetX (); 180 | var traveledDistance = (int)Math.Round (Math.Abs (x - (startX))); 181 | SetNewOffset (stateBeforeTracking ? 182 | MaxOffset - Math.Min (MaxOffset, traveledDistance) 183 | : Math.Max (0, traveledDistance)); 184 | } else if (e.Action == MotionEventActions.Up 185 | && stateBeforeTracking == opened) { 186 | velocityTracker.ComputeCurrentVelocity (1000, maxFlingVelocity); 187 | if (Math.Abs (velocityTracker.XVelocity) > minFlingVelocity) 188 | SetOpened (!opened); 189 | else if (!opened && contentOffsetX > MaxOffset / 2) 190 | SetOpened (true); 191 | else if (opened && contentOffsetX < MaxOffset / 2) 192 | SetOpened (false); 193 | else 194 | SetOpened (opened); 195 | 196 | preTracking = isTracking = false; 197 | } 198 | 199 | return true; 200 | } 201 | 202 | bool CaptureMovementCheck (MotionEvent ev) 203 | { 204 | if (ev.Action == MotionEventActions.Down) { 205 | startX = (int)ev.GetX (); 206 | startY = (int)ev.GetY (); 207 | 208 | // Only work if the initial touch was in the start strip when the menu is closed 209 | // When the menu is opened, anywhere will do 210 | if (!opened && (startX > Context.ToPixels (30))) 211 | return false; 212 | 213 | velocityTracker = VelocityTracker.Obtain (); 214 | velocityTracker.AddMovement (ev); 215 | preTracking = true; 216 | stateBeforeTracking = opened; 217 | return false; 218 | } 219 | 220 | if (ev.Action == MotionEventActions.Up) 221 | preTracking = isTracking = false; 222 | 223 | if (!preTracking) 224 | return false; 225 | 226 | velocityTracker.AddMovement (ev); 227 | 228 | if (ev.Action == MotionEventActions.Move) { 229 | 230 | // Check we are going in the right direction, if not cancel the current gesture 231 | if (!MoveDirectionTest (ev)) { 232 | preTracking = false; 233 | return false; 234 | } 235 | 236 | // If the current gesture has not gone long enough don't intercept it just yet 237 | var distance = Math.Sqrt (Math.Pow (ev.GetX () - startX, 2) + Math.Pow (ev.GetY () - startY, 2)); 238 | if (distance < pagingTouchSlop) 239 | return false; 240 | } 241 | 242 | startX = (int)ev.GetX (); 243 | startY = (int)ev.GetY (); 244 | isTracking = true; 245 | 246 | return true; 247 | } 248 | 249 | // Check that movement is in a common vertical area and that we are going in the right direction 250 | bool MoveDirectionTest (MotionEvent e) 251 | { 252 | return (stateBeforeTracking ? e.GetX () <= startX : e.GetX () >= startX) 253 | && Math.Abs (e.GetY () - startY) < touchSlop; 254 | } 255 | 256 | protected override void DispatchDraw (Android.Graphics.Canvas canvas) 257 | { 258 | base.DispatchDraw (canvas); 259 | 260 | if (opened || isTracking || animator != null) { 261 | // Draw inset shadow on the menu 262 | canvas.Save (); 263 | shadowDrawable.SetBounds (0, 0, Context.ToPixels (8), Height); 264 | canvas.Translate (ContentView.Left - shadowDrawable.Bounds.Width (), 0); 265 | shadowDrawable.Draw (canvas); 266 | canvas.Restore (); 267 | 268 | if (contentOffsetX != 0) { 269 | // Cover the area with a black overlay to display openess graphically 270 | var openness = ((float)(MaxOffset - contentOffsetX)) / MaxOffset; 271 | overlayPaint.Alpha = Math.Max (0, (int)(MaxOverlayAlpha * openness)); 272 | if (overlayPaint.Alpha > 0) 273 | canvas.DrawRect (0, 0, ContentView.Left, Height, overlayPaint); 274 | } 275 | } 276 | } 277 | 278 | class SmoothInterpolator : Java.Lang.Object, ITimeInterpolator 279 | { 280 | public float GetInterpolation (float input) 281 | { 282 | return (float)Math.Pow (input - 1, 5) + 1; 283 | } 284 | } 285 | } 286 | 287 | static class DensityExtensions 288 | { 289 | static readonly DisplayMetrics displayMetrics = new DisplayMetrics (); 290 | 291 | public static int ToPixels (this Context ctx, int dp) 292 | { 293 | var wm = ctx.GetSystemService (Context.WindowService).JavaCast (); 294 | wm.DefaultDisplay.GetMetrics (displayMetrics); 295 | 296 | var density = displayMetrics.Density; 297 | return (int)(dp * density + 0.5f); 298 | } 299 | } 300 | } 301 | 302 | -------------------------------------------------------------------------------- /FlyOutMenu/FlyOutMenu.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.0 7 | 2.0 8 | {DC4A371A-1B94-4270-9EB6-F44A59153567} 9 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Library 11 | FlyOutMenu 12 | True 13 | Resources\Resource.designer.cs 14 | Resource 15 | Resources 16 | Assets 17 | FlyOutMenu 18 | v4.0.3 19 | Properties\AndroidManifest.xml 20 | 21 | 22 | true 23 | false 24 | bin\Debug 25 | DEBUG; 26 | prompt 27 | 4 28 | None 29 | false 30 | true 31 | 32 | 33 | true 34 | bin\Release 35 | prompt 36 | 4 37 | false 38 | SdkOnly 39 | false 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /FlyOutMenu/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Android.App; 4 | using Android.Content; 5 | using Android.Runtime; 6 | using Android.Views; 7 | using Android.Widget; 8 | using Android.OS; 9 | 10 | namespace FlyOutMenu 11 | { 12 | [Activity (Label = "FlyInMenu", MainLauncher = true, Theme = "@android:style/Theme.Holo.Light.NoActionBar")] 13 | public class Activity1 : Activity 14 | { 15 | protected override void OnCreate (Bundle bundle) 16 | { 17 | base.OnCreate (bundle); 18 | 19 | // Set our view from the "main" layout resource 20 | SetContentView (Resource.Layout.Main); 21 | 22 | var menu = FindViewById (Resource.Id.FlyOutContainer); 23 | var menuButton = FindViewById (Resource.Id.MenuButton); 24 | menuButton.Click += (sender, e) => { 25 | menu.AnimatedOpened = !menu.AnimatedOpened; 26 | }; 27 | } 28 | } 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /FlyOutMenu/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FlyOutMenu/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using Android.App; 4 | 5 | // Information about this assembly is defined by the following attributes. 6 | // Change them to the values specific to your project. 7 | 8 | [assembly: AssemblyTitle("FlyInMenu")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("jeremie")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 20 | 21 | [assembly: AssemblyVersion("1.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | 29 | -------------------------------------------------------------------------------- /FlyOutMenu/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.axml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.axml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. 45 | -------------------------------------------------------------------------------- /FlyOutMenu/Resources/Resource.designer.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Mono Runtime Version: 4.0.30319.17020 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | // ------------------------------------------------------------------------------ 10 | 11 | [assembly: Android.Runtime.ResourceDesignerAttribute("FlyOutMenu.Resource", IsApplication=true)] 12 | 13 | namespace FlyOutMenu 14 | { 15 | 16 | 17 | public partial class Resource 18 | { 19 | 20 | public static void UpdateIdValues() 21 | { 22 | } 23 | 24 | public partial class Attribute 25 | { 26 | 27 | private Attribute() 28 | { 29 | } 30 | } 31 | 32 | public partial class Drawable 33 | { 34 | 35 | // aapt resource value: 0x7f020000 36 | public const int action_menu = 2130837504; 37 | 38 | // aapt resource value: 0x7f020001 39 | public const int Icon = 2130837505; 40 | 41 | // aapt resource value: 0x7f020002 42 | public const int icon1 = 2130837506; 43 | 44 | // aapt resource value: 0x7f020003 45 | public const int iconelse = 2130837507; 46 | 47 | private Drawable() 48 | { 49 | } 50 | } 51 | 52 | public partial class Id 53 | { 54 | 55 | // aapt resource value: 0x7f050008 56 | public const int FlyOutContainer = 2131034120; 57 | 58 | // aapt resource value: 0x7f050000 59 | public const int FlyOutContent = 2131034112; 60 | 61 | // aapt resource value: 0x7f050009 62 | public const int FlyOutMenu = 2131034121; 63 | 64 | // aapt resource value: 0x7f050004 65 | public const int MenuButton = 2131034116; 66 | 67 | // aapt resource value: 0x7f050002 68 | public const int frameLayout1 = 2131034114; 69 | 70 | // aapt resource value: 0x7f05000a 71 | public const int imageView1 = 2131034122; 72 | 73 | // aapt resource value: 0x7f05000c 74 | public const int imageView2 = 2131034124; 75 | 76 | // aapt resource value: 0x7f050003 77 | public const int linearLayout1 = 2131034115; 78 | 79 | // aapt resource value: 0x7f05000b 80 | public const int linearLayout2 = 2131034123; 81 | 82 | // aapt resource value: 0x7f050007 83 | public const int textView1 = 2131034119; 84 | 85 | // aapt resource value: 0x7f050005 86 | public const int textView2 = 2131034117; 87 | 88 | // aapt resource value: 0x7f05000d 89 | public const int textView3 = 2131034125; 90 | 91 | // aapt resource value: 0x7f050001 92 | public const int view1 = 2131034113; 93 | 94 | // aapt resource value: 0x7f050006 95 | public const int view2 = 2131034118; 96 | 97 | // aapt resource value: 0x7f05000e 98 | public const int view3 = 2131034126; 99 | 100 | private Id() 101 | { 102 | } 103 | } 104 | 105 | public partial class Layout 106 | { 107 | 108 | // aapt resource value: 0x7f030000 109 | public const int ContentLayout = 2130903040; 110 | 111 | // aapt resource value: 0x7f030001 112 | public const int Main = 2130903041; 113 | 114 | // aapt resource value: 0x7f030002 115 | public const int MenuLayout = 2130903042; 116 | 117 | private Layout() 118 | { 119 | } 120 | } 121 | 122 | public partial class String 123 | { 124 | 125 | // aapt resource value: 0x7f040001 126 | public const int app_name = 2130968577; 127 | 128 | // aapt resource value: 0x7f040000 129 | public const int hello = 2130968576; 130 | 131 | private String() 132 | { 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable-xhdpi/action_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable-xhdpi/action_menu.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable-xhdpi/icon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable-xhdpi/icon1.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable-xhdpi/iconelse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable-xhdpi/iconelse.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable/Icon.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable/action_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable/action_menu.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable/icon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable/icon1.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/drawable/iconelse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garuma/FlyOutMenu/e531ab5414623d48099a2582a6266cf6eab02bdf/FlyOutMenu/Resources/drawable/iconelse.png -------------------------------------------------------------------------------- /FlyOutMenu/Resources/layout/ContentLayout.axml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 18 | 23 | 29 | 38 | 39 | 40 | 45 | 52 | -------------------------------------------------------------------------------- /FlyOutMenu/Resources/layout/Main.axml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | 10 | -------------------------------------------------------------------------------- /FlyOutMenu/Resources/layout/MenuLayout.axml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 17 | 25 | 33 | 38 | 47 | 48 | 56 | 64 | 69 | 78 | 79 | 87 | -------------------------------------------------------------------------------- /FlyOutMenu/Resources/values/Strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello World, Click Me! 4 | FlyInMenu 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FlyOutMenu 2 | ========== 3 | 4 | An implementation of a fly-out menu (aka sliding menu, aka that navigation thing on the left) for [Xamarin.Android](http://xamarin.com/android) 5 | 6 |

7 | 8 |
Our menu in its different states when right slided 9 |

10 | 11 | Blog post introducing this code: [blog.neteril.org/blog/2013/04/19/fly-out-menu-xamarin-android/](https://blog.neteril.org/blog/2013/04/19/fly-out-menu-xamarin-android/) 12 | 13 | ## Note 14 | 15 | There is now an Android [blessed implementation](http://developer.android.com/design/patterns/navigation-drawer.html) of this pattern in the support package but this code is still useful as a learning experience or if you want to be able to have a fully customized slider. 16 | 17 | ## License 18 | 19 | This code is available under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). Reuse as much as you want. 20 | --------------------------------------------------------------------------------