diff --git a/Droid/Assets/qfont.ttf b/Droid/Assets/qfont.ttf index bffb24c..35c6f70 100755 Binary files a/Droid/Assets/qfont.ttf and b/Droid/Assets/qfont.ttf differ diff --git a/Droid/Properties/AndroidManifest.xml b/Droid/Properties/AndroidManifest.xml index a8f7809..ecdf539 100644 --- a/Droid/Properties/AndroidManifest.xml +++ b/Droid/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/iOS/Info.plist b/iOS/Info.plist index 3ddfc04..64ba5ec 100644 --- a/iOS/Info.plist +++ b/iOS/Info.plist @@ -36,7 +36,7 @@ XSAppIconAssets Assets.xcassets/AppIcon.appiconset CFBundleShortVersionString - 2.0.7 + 2.0.8 CFBundleVersion 1.0 ITSAppUsesNonExemptEncryption diff --git a/iOS/Resources/qfont.ttf b/iOS/Resources/qfont.ttf index bffb24c..35c6f70 100755 Binary files a/iOS/Resources/qfont.ttf and b/iOS/Resources/qfont.ttf differ diff --git a/qController.Standard/Classes/Cell/QCueListCell.cs b/qController.Standard/Classes/Cell/QCueListCell.cs new file mode 100644 index 0000000..ea58e56 --- /dev/null +++ b/qController.Standard/Classes/Cell/QCueListCell.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.ObjectModel; +using Xamarin.Forms; + +namespace qController +{ + public class QCueListCell : Frame + { + public ListView cueListView; + public Button closeButton; + public QCueListCell(QCueList qCueList) + { + Margin = new Thickness(10); + Padding = new Thickness(10); + + + cueListView = new ListView + { + ItemsSource = qCueList.cues, + RowHeight = (int)(App.HeightUnit * 6), + ItemTemplate = new DataTemplate(() => + { + var grid = new Grid { Padding = new Thickness(5, 10) }; + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(30) }); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star }); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(30) }); + + + var icon = new Label(); + icon.FontFamily = App.QFont; + icon.SetBinding(Label.TextProperty, "IconText"); + icon.HorizontalTextAlignment = TextAlignment.Center; + icon.VerticalTextAlignment = TextAlignment.Center; + icon.FontSize = App.HeightUnit * 3; + + var label = new Label { VerticalOptions = LayoutOptions.FillAndExpand }; + label.SetBinding(Label.TextProperty, "listName"); + + switch (Device.RuntimePlatform) + { + case Device.iOS: + label.FontSize = App.HeightUnit * 3; + break; + case Device.Android: + label.FontSize = App.HeightUnit * 2.2; + break; + } + var selectedLabel = new Label { + VerticalOptions = LayoutOptions.FillAndExpand, + FontFamily = App.QFont, + Text = QIcon.LEFT_DIR, + TextColor = Color.Green, + FontSize = App.HeightUnit * 3 + }; + + grid.Children.Add(icon, 0, 0); + grid.Children.Add(label, 1, 0); + //grid.Children.Add(selectedLabel, 2, 0); + return new ViewCell { View = grid }; + + }) + }; + StackLayout layout = new StackLayout(); + closeButton = new Button + { + BackgroundColor = Color.Gray, + Text = "Close", + TextColor = Color.White + }; + + layout.Children.Add(closeButton); + layout.Children.Add(cueListView); + Content = layout; + + } + } +} diff --git a/qController.Standard/Classes/Communication/QController.cs b/qController.Standard/Classes/Communication/QController.cs index 9b647dd..76ddfb9 100644 --- a/qController.Standard/Classes/Communication/QController.cs +++ b/qController.Standard/Classes/Communication/QController.cs @@ -14,10 +14,15 @@ namespace qController public QClient qClient; public QWorkspace qWorkspace; public string playbackPosition; - public Stopwatch sw; + private string ipAddress; + private int port; + public QController(string address, int port) { - qClient = new QClient(address, port); + this.port = port; + this.ipAddress = address; + + qClient = new QClient(ipAddress, port); qUpdater = new QUpdater(this); } @@ -25,8 +30,7 @@ namespace qController public void Connect(string workspace_id) { Console.WriteLine("QCONTROLLER CONNECT CALLED: " + workspace_id); - qWorkspace = new QWorkspace(); - qWorkspace.workspace_id = workspace_id; + qWorkspace = new QWorkspace(workspace_id); qUpdater.Start(); qClient.sendArgsUDP("/workspace/"+workspace_id+"/connect"); qClient.sendArgsUDP("/workspace/"+workspace_id+"/updates", 1); @@ -48,6 +52,16 @@ namespace qController qClient.sendArgsUDP("/workspace/" + qWorkspace.workspace_id + "/connect", pass); } + public void Resume() + { + //qClient = new QClient(ipAddress, port); + //qUpdater = new QUpdater(this); + if(qWorkspace != null) + { + Console.WriteLine("RESUMING " + qWorkspace.workspace_id); + } + } + public void Kill(){ if (qUpdater != null) qUpdater.Kill(); diff --git a/qController.Standard/Classes/Communication/QParser.cs b/qController.Standard/Classes/Communication/QParser.cs index e272e8e..b4999c4 100644 --- a/qController.Standard/Classes/Communication/QParser.cs +++ b/qController.Standard/Classes/Communication/QParser.cs @@ -80,6 +80,8 @@ namespace qController public delegate void ChildrenUpdateHandler(object source, ChildrenEventArgs args); public delegate void WorkspaceDisconnectHandler(object source, EventArgs args); public delegate void WorkspaceInfoHandler(object source, WorkspaceInfoArgs args); + public delegate void WorkspaceLoadErrorHandler(object source, WorkspaceEventArgs args); + public event WorkspaceLoadErrorHandler WorkspaceLoadError; public event WorkspaceInfoHandler WorkspaceInfoReceived; public event WorkspaceDisconnectHandler WorkspaceDisconnect; public event ChildrenUpdateHandler ChildrenUpdated; @@ -162,8 +164,29 @@ namespace qController { if (msg.Arguments.Count > 0) { - QWorkspace workspace = JsonConvert.DeserializeObject(msg.Arguments[0].ToString()); - OnWorkspaceUpdated(workspace); + var parts = msg.Address.Split('/'); + string id = parts[3]; + + if (msg.Arguments[0].ToString() != "") + { + try + { + Console.WriteLine(msg.Arguments.Count); + Console.WriteLine(msg.Arguments[0].ToString().Length); + + QWorkspace workspace = JsonConvert.DeserializeObject(msg.Arguments[0].ToString()); + OnWorkspaceUpdated(workspace); + } + catch (Exception ex) + { + OnWorkspaceLoadError(id); + } + + } + else + { + OnWorkspaceLoadError(id); + } } } @@ -225,6 +248,11 @@ namespace qController if (WorkspaceInfoReceived != null) WorkspaceInfoReceived(this, new WorkspaceInfoArgs() { WorkspaceInfo = workspaces }); } + protected virtual void OnWorkspaceLoadError(string id) + { + if (WorkspaceLoadError != null) + WorkspaceLoadError(this, new WorkspaceEventArgs { UpdatedWorkspace = new QWorkspace(id) }); + } } } diff --git a/qController.Standard/Classes/Communication/QUpdater.cs b/qController.Standard/Classes/Communication/QUpdater.cs index ea7bf3f..e0a9833 100644 --- a/qController.Standard/Classes/Communication/QUpdater.cs +++ b/qController.Standard/Classes/Communication/QUpdater.cs @@ -18,6 +18,16 @@ namespace qController qController.qClient.qParser.CueInfoUpdated += OnCueUpdateReceived; qController.qClient.qParser.WorkspaceUpdated += OnWorkspaceUpdated; qController.qClient.qParser.PlaybackPositionUpdated += OnPlaybackPositionUpdated; + qController.qClient.qParser.WorkspaceLoadError += OnWorkspaceLoadError; + + } + + private void OnWorkspaceLoadError(object source, WorkspaceEventArgs args) + { + Console.WriteLine("QUpdater: Loading cuelists has failed for some reason retrying"); + qController.qClient.sendArgsUDP("/workspace/" + args.UpdatedWorkspace.workspace_id + "/connect"); + qController.qClient.sendArgsUDP("/workspace/" + args.UpdatedWorkspace.workspace_id + "/updates", 1); + qController.qClient.sendAndReceiveString("/workspace/" + args.UpdatedWorkspace.workspace_id + "/cueLists"); } @@ -25,7 +35,7 @@ namespace qController updateThread.Start(); } - //Attemp at a "keep alive" message + //Attempt at a "keep alive" message public void UpdateLoop() { active = true; @@ -64,6 +74,7 @@ namespace qController public void OnPlaybackPositionUpdated(object source, PlaybackPositionArgs args) { qController.playbackPosition = args.PlaybackPosition; + Console.WriteLine("ControlPage: Update Specific Cue Called because of Playback Position Updated"); qController.qClient.UpdateSpecificCue(qController.qWorkspace.workspace_id,args.PlaybackPosition); } diff --git a/qController.Standard/Classes/Cues/QCue.cs b/qController.Standard/Classes/Cues/QCue.cs index a5e202f..38174a9 100644 --- a/qController.Standard/Classes/Cues/QCue.cs +++ b/qController.Standard/Classes/Cues/QCue.cs @@ -30,7 +30,7 @@ namespace qController public bool isLoaded { get; set; } public string notes { get; set; } public List> levels { get; set; } - + //info loaded from /children public List cues { get; set; } @@ -39,5 +39,13 @@ namespace qController { return QIcon.GetIconFromType(type); } + + public string IconText + { + get + { + return QIcon.GetIconFromType(type); + } + } } } diff --git a/qController.Standard/Classes/Cues/QCueList.cs b/qController.Standard/Classes/Cues/QCueList.cs index fe78db6..62a833c 100644 --- a/qController.Standard/Classes/Cues/QCueList.cs +++ b/qController.Standard/Classes/Cues/QCueList.cs @@ -13,5 +13,13 @@ namespace qController public string colorName { get; set; } public string name { get; set; } public bool armed { get; set; } + + public string IconText + { + get + { + return QIcon.LIST; + } + } } } diff --git a/qController.Standard/Classes/Cues/QWorkSpace.cs b/qController.Standard/Classes/Cues/QWorkSpace.cs index cfbad43..6d20e0e 100644 --- a/qController.Standard/Classes/Cues/QWorkSpace.cs +++ b/qController.Standard/Classes/Cues/QWorkSpace.cs @@ -13,6 +13,12 @@ namespace qController public string address { get; set; } public bool IsPopulated { get; set; } + //ONLY FOR PASSING A WORKSPACE LOAD ERROR + public QWorkspace(string id) + { + workspace_id = id; + } + public QCue GetCue(string cue_id) { foreach (var cueList in data) @@ -28,6 +34,18 @@ namespace qController return null; } + public QCueList GetCueList(string id) + { + foreach (var cueList in data) + { + if(cueList.uniqueID == id) + { + return cueList; + } + } + return null; + } + public void UpdateCue(QCue cue) { for (int i = 0; i < data.Count; i++) diff --git a/qController.Standard/Classes/Settings/QIcon.cs b/qController.Standard/Classes/Settings/QIcon.cs index a69c06a..4c48783 100644 --- a/qController.Standard/Classes/Settings/QIcon.cs +++ b/qController.Standard/Classes/Settings/QIcon.cs @@ -49,6 +49,8 @@ public const string DOLLAR = "\uF155"; public const string MAIL = "\uE812"; + public const string LEFT_DIR = "\uE813"; + public const string LIST = "\uE814"; public static string GetIconFromType(string type) { diff --git a/qController.Standard/Pages/App.xaml.cs b/qController.Standard/Pages/App.xaml.cs index e1e90c4..f8c0508 100644 --- a/qController.Standard/Pages/App.xaml.cs +++ b/qController.Standard/Pages/App.xaml.cs @@ -1,7 +1,7 @@ using Acr.UserDialogs; using Xamarin.Forms; using Xamarin.Essentials; - +using System; namespace qController { public partial class App : Application @@ -15,7 +15,7 @@ namespace qController public static double Width; public static double HeightUnit; public static double WidthUnit; - + public static QController qControllerToResume; public static bool MenuIsPresented { get @@ -61,22 +61,6 @@ namespace qController rootPage.Init(); } - protected override void OnStart() - { - // Handle when your app starts - - } - - protected override void OnSleep() - { - // Handle when your app sleeps - } - - protected override void OnResume() - { - // Handle when your app resumes - } - public static void showToast(string message) { var toastConfig = new ToastConfig(message); diff --git a/qController.Standard/Pages/ControlPage.xaml.cs b/qController.Standard/Pages/ControlPage.xaml.cs index ad8174b..b2ca4e5 100644 --- a/qController.Standard/Pages/ControlPage.xaml.cs +++ b/qController.Standard/Pages/ControlPage.xaml.cs @@ -10,8 +10,8 @@ namespace qController QController qController; QSelectedCueCell qCell; QLevelsCell qLevelsCell; + QCueListCell qCueListCell; ShadowButton showLevelsButton; - Grid mainG; QControlsBlock qControlsBlock; public ControlPage(string name, string address) { @@ -23,6 +23,7 @@ namespace qController qController.qClient.qParser.PlaybackPositionUpdated += PlaybackPositionUpdated; qController.qClient.qParser.CueInfoUpdated += OnCueUpdateReceived; qController.qClient.qParser.ChildrenUpdated += OnChildrenUpdated; + App.rootPage.MenuItemSelected += OnMenuItemSelected; instanceName.Text = name; @@ -36,14 +37,13 @@ namespace qController { if(args.WorkspaceInfo.Count > 1) { - Console.WriteLine("MULTIPLE WORKSPACES ON SELECTED COMPUTER"); + Console.WriteLine("ControlPage: MULTIPLE WORKSPACES ON SELECTED COMPUTER"); PromptForWorkspace(args.WorkspaceInfo); } else { - Console.WriteLine("ONLY ONE WORKSPACE ON SELECTED COMPUTER"); + Console.WriteLine("ControlPage: ONLY ONE WORKSPACE ON SELECTED COMPUTER"); qController.Connect(args.WorkspaceInfo[0].uniqueID); - Device.BeginInvokeOnMainThread(() => { FinishUI(); }); @@ -58,7 +58,7 @@ namespace qController { QWorkspaceInfo workspace = workspaces[i]; config.Add(workspace.displayName, new Action(() => { - Console.WriteLine("Workspace Selected: " + workspace.displayName); + Console.WriteLine("ControlPage: Workspace Selected " + workspace.displayName); qController.Connect(workspace.uniqueID); Device.BeginInvokeOnMainThread(() => { @@ -87,22 +87,23 @@ namespace qController { case Device.iOS: AbsoluteLayout.SetLayoutBounds(qCell, new Rectangle(0, 0.13, 1, 0.30)); - topBar.HeightRequest = Math.Max(App.Height * .09, 65); - menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); + topBar.HeightRequest = App.Height * .09; menuButton.FontSize = App.Height * .04; break; case Device.Android: AbsoluteLayout.SetLayoutBounds(qCell, new Rectangle(0, 0.13, 1, 0.35)); - topBar.HeightRequest = App.Height * .08; - menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); + topBar.HeightRequest = App.Height * .06; menuButton.FontSize = App.Height * .05; break; } + + //Menu Button Setup var menuButtonGesture = new TapGestureRecognizer(); menuButtonGesture.Tapped += ShowMenu; menuButton.GestureRecognizers.Add(menuButtonGesture); - + menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); + sLayout.Children.Add(qCell); } @@ -156,6 +157,7 @@ namespace qController AbsoluteLayout.SetLayoutFlags(qLevelsCell, AbsoluteLayoutFlags.All); AbsoluteLayout.SetLayoutFlags(showLevelsButton, AbsoluteLayoutFlags.PositionProportional); + switch (Device.RuntimePlatform) { case Device.iOS: @@ -183,11 +185,13 @@ namespace qController void Back() { qController.Disconnect(); + qController.Kill(); + App.rootPage.MenuItemSelected -= OnMenuItemSelected; Device.BeginInvokeOnMainThread(() => { App.rootPage.MenuPage.ChangeToHome(); + App.NavigationPage.Navigation.PopAsync(); }); - App.NavigationPage.Navigation.PopAsync(); } public void WorkspaceUpdated(object sender, WorkspaceEventArgs e) @@ -213,9 +217,10 @@ namespace qController noSelect.number = "!"; qCell.UpdateSelectedCue(noSelect); }); + Console.WriteLine("ControlPage: Update Selected Cue Called because of Inital Workspace Load"); qController.qClient.UpdateSelectedCue(qController.qWorkspace.workspace_id); } - Console.WriteLine("Workspace updated in ControlPage: " + qController.qWorkspace.workspace_id); + Console.WriteLine("ControlPage: Workspace Updated " + qController.qWorkspace.workspace_id); } } } @@ -223,7 +228,7 @@ namespace qController public void PlaybackPositionUpdated(object sender, PlaybackPositionArgs e) { qController.playbackPosition = e.PlaybackPosition; - Console.WriteLine("Playback Position updated in ControlPage: " + qController.playbackPosition); + Console.WriteLine("ControlPage: Playback Position Updated " + qController.playbackPosition); QCue cue = qController.qWorkspace.GetCue(qController.playbackPosition); if(cue != null) { @@ -242,50 +247,53 @@ namespace qController public void OnCueUpdateReceived(object sender, CueEventArgs args) { - qController.qWorkspace.UpdateCue(args.Cue); - Device.BeginInvokeOnMainThread(() => + if(qController != null) { - App.rootPage.MenuPage.ChangeCueName(args.Cue.uniqueID, args.Cue.listName); - }); - if (qController.playbackPosition == null) - { - qController.playbackPosition = args.Cue.uniqueID; - } - - if (args.Cue.uniqueID == qController.playbackPosition) - { - Device.BeginInvokeOnMainThread(() => + if(qController.qWorkspace != null) { - Console.WriteLine("Refreshing Currently Displayed Cue"); - if (args.Cue.levels != null) - showLevelsButton.IsVisible = true; - else + qController.qWorkspace.UpdateCue(args.Cue); + if (qController.playbackPosition == null) { - showLevelsButton.IsVisible = false; - qLevelsCell.IsVisible = false; + qController.playbackPosition = args.Cue.uniqueID; } - qCell.UpdateSelectedCue(args.Cue); - if(qLevelsCell != null) + + if (args.Cue.uniqueID == qController.playbackPosition) { - qLevelsCell.activeCue = args.Cue.uniqueID; - if (args.Cue.levels != null) + Device.BeginInvokeOnMainThread(() => { - qLevelsCell.UpdateLevels(args.Cue.levels[0]); - } - } - }); + Console.WriteLine("ControlPage: Refreshing Currently Displayed Cue"); + if (args.Cue.levels != null) + showLevelsButton.IsVisible = true; + else + { + showLevelsButton.IsVisible = false; + qLevelsCell.IsVisible = false; + } + qCell.UpdateSelectedCue(args.Cue); + if(qLevelsCell != null) + { + qLevelsCell.activeCue = args.Cue.uniqueID; + if (args.Cue.levels != null) + { + qLevelsCell.UpdateLevels(args.Cue.levels[0]); + } + } + }); + } + } } + } private void OnChildrenUpdated(object source, ChildrenEventArgs args) { - Console.WriteLine("Children Updated in ControlPage: " + args.cue_id); - qController.qWorkspace.UpdateChildren(args.cue_id, args.children); - Device.BeginInvokeOnMainThread(() => + if(qController != null) { - App.rootPage.MenuPage.ChangeToControl(); - App.rootPage.MenuPage.ChangeToWorkspace(qController.qWorkspace); - }); + if(qController.qWorkspace != null) + { + qController.qWorkspace.UpdateChildren(args.cue_id, args.children); + } + } } private void OnMenuItemSelected(object source, MenuEventArgs args) @@ -297,19 +305,55 @@ namespace qController else if (args.Command == "disconnect") { Back(); + }else if (args.Command.Contains("cueList")) + { + var parts = args.Command.Split(' '); + if(parts.Length > 1) + { + Device.BeginInvokeOnMainThread(() => + { + qCueListCell = new QCueListCell(qController.qWorkspace.GetCueList(parts[1])); + qCueListCell.closeButton.Clicked += CloseCueList; + qCueListCell.cueListView.ItemSelected += OnCueListItemSelected; + AbsoluteLayout.SetLayoutFlags(qCueListCell, AbsoluteLayoutFlags.All); + AbsoluteLayout.SetLayoutBounds(qCueListCell, new Rectangle(0, 0.2, 1, 0.9)); + sLayout.Children.Add(qCueListCell); + }); + } } } - protected override void OnDisappearing() + private void CloseCueList(object sender, EventArgs e) { - base.OnDisappearing(); - Console.WriteLine("Disappeared"); - qController.Kill(); + CloseCueList(); } - protected override void OnAppearing() + + private void CloseCueList() { - base.OnAppearing(); - Console.WriteLine("Appeared"); + Device.BeginInvokeOnMainThread(() => + { + sLayout.Children.Remove(qCueListCell); + }); + } + + private void OnCueListItemSelected(object sender, SelectedItemChangedEventArgs e) + { + QCue cue = (QCue)e.SelectedItem; + string selectCueOSC = "/workspace/" + qController.qWorkspace.workspace_id + "/select_id/" + cue.uniqueID; + qController.qClient.sendStringUDP(selectCueOSC); + CloseCueList(); + } + + protected override bool OnBackButtonPressed() + { + qController.Disconnect(); + qController.Kill(); + App.rootPage.MenuItemSelected -= OnMenuItemSelected; + Device.BeginInvokeOnMainThread(() => + { + App.rootPage.MenuPage.ChangeToHome(); + }); + return base.OnBackButtonPressed(); } } } diff --git a/qController.Standard/Pages/MenuPage.xaml.cs b/qController.Standard/Pages/MenuPage.xaml.cs index ce94641..bc78fbe 100644 --- a/qController.Standard/Pages/MenuPage.xaml.cs +++ b/qController.Standard/Pages/MenuPage.xaml.cs @@ -82,77 +82,12 @@ namespace qController items.Add(new MenuPageItem { Title = cueList.listName, - Icon = "", - Command = "" - }); - for (int j = 0; j < cueList.cues.Count; j++) - { - var cue = cueList.cues[j]; - AddSubCues(cue, 0); - } - } - } - - public void AddSubCues(QCue cue, int level) - { - var cueIcon = cue.getIconString(); - var cueTitle = ""; - for (int i = 0; i < level; i++) - { - cueTitle += " "; - } - if (cue.number != "") - { - cueTitle += cue.number + " - " + cue.listName; - } - else - { - cueTitle += cue.listName; - } - - if (cue.cues != null ) - { - items.Add(new MenuPageItem - { - Title = cueTitle, - Icon = cueIcon, - Command = "/select_id/" + cue.uniqueID - }); - - //uncomment to load nested group cues - for (int i = 0; i < cue.cues.Count; i++) - { - var sub_cue = cue.cues[i]; - AddSubCues(sub_cue, level + 1); - } - } - else - { - items.Add(new MenuPageItem - { - Title = cueTitle, - Icon = cueIcon, - Command = "/select_id/" + cue.uniqueID + Icon = cueList.IconText, + Command = "cueList " + cueList.uniqueID }); } } - public void ChangeCueName(string cue_id, string name){ - for(int i = 0; i < items.Count; i++) - { - if (items[i].Command.Contains(cue_id)) - { - var item = items[i]; - items.RemoveAt(i); - item.Title = name; - items.Insert(i, item); - Console.WriteLine("CUE OBJECT FOUND IN MENU TRYING TO UPDATE"); - return; - } - } - - } - public void ChangeToHome() { items.Clear(); diff --git a/qController.Standard/Pages/qConnectionPage.xaml.cs b/qController.Standard/Pages/qConnectionPage.xaml.cs index 9c10791..92d767c 100644 --- a/qController.Standard/Pages/qConnectionPage.xaml.cs +++ b/qController.Standard/Pages/qConnectionPage.xaml.cs @@ -67,10 +67,12 @@ namespace qController case Device.iOS: topBar.HeightRequest = App.Height * .09; menuButton.FontSize = App.Height * .04; + menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); break; case Device.Android: - topBar.HeightRequest = App.Height * .08; + topBar.HeightRequest = App.Height * .09; menuButton.FontSize = App.Height * .05; + menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); break; } @@ -80,7 +82,6 @@ namespace qController var menuButtonGesture = new TapGestureRecognizer(); menuButtonGesture.Tapped += showMenu; menuButton.GestureRecognizers.Add(menuButtonGesture); - menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); }