In development for iOS and Android devices, Disc Golf Buddy is a way for disc golf clubs and it's members to quickly calculate tag sorting at the end of a round, as well as provide a web portal to easily access club standings.
- Developed in Xamarin Forms for Visual Studio and programmed in C#.
- Utilizes Amazon Web Services for user authentication and remote database and storage functions.
- A custom Developer Authentication Mechanism developed using a serverless approach by taking advantage of AWS Lambda,
DynamoDB and Cognito along with other AWS services.
- Local data stored using SQLite.
- Soon to be published on Apple's App Store and Google Play.
/**
* LoadPage.xaml
* LoadPage XAML layout.
* NicholusHuber@gmail.com
*/
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DGB.LoadPage">
<StackLayout x:Name="_stackLayoutMain" Orientation="Vertical" HorizontalOptions="Center" >
<Image x:Name="_imageTextLogo" Source="intropagetextlogo.jpg" />
<Grid x:Name="_gridMainLabels" ColumnSpacing="5" BackgroundColor="Black" >
<Label x:Name="_labelName" Text="GAME NAME" Grid.Column="0" HorizontalTextAlignment="Start" HorizontalOptions="StartAndExpand" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"/>
<Label x:Name="_labelDate" Text="LAST MODIFIED" Grid.Column="1" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"/>
</Grid>
<ListView x:Name="_listViewMain" />
<Button x:Name="_buttonLoad" Text="Load Game" Clicked="LoadButton_OnClicked" IsEnabled="False"/>
<Button x:Name="_buttonDelete" Text="Delete Game" Clicked="DeleteButton_OnClicked" IsEnabled="False"/>
<Button x:Name="_buttonCancel" Text="Cancel" Clicked="CancelButton_OnClicked" />
</StackLayout>
</ContentPage>
/**
* LoadPage.xaml.cs
* Underlying functionality for the LoadPage XAML form.
* NicholusHuber@gmail.com
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.Forms;
namespace DGB
{
public partial class LoadPage
{
private List<GameInfo> _gameList;
private readonly IntroPage _introPage;
private readonly List<VisualElement> _buttons;
public LoadPage(IntroPage introPage)
{
InitializeComponent();
_introPage = introPage;
_gameList = Player.GetSaveGameInfo();
_buttons = new List<VisualElement> { _buttonLoad, _buttonDelete, _buttonCancel };
SetUiScale();
}
/// <summary>
/// Sets local UI elements sizes to scale with device resolution.
/// </summary>
private void SetUiScale()
{
if(Device.OS == TargetPlatform.iOS) Padding = new Thickness(0,10,0,0);
_imageTextLogo.HeightRequest = App.ScreenHeight * 0.116f;
_stackLayoutMain.Margin = App.MarginSize;
_buttonLoad.HeightRequest = App.ButtonHeight;
_buttonLoad.WidthRequest = App.ButtonWidth;
_buttonLoad.FontSize = App.FontSizeLarge;
_buttonDelete.HeightRequest = App.ButtonHeight;
_buttonDelete.WidthRequest = App.ButtonWidth;
_buttonDelete.FontSize = App.FontSizeLarge;
_buttonCancel.HeightRequest = App.ButtonHeight;
_buttonCancel.WidthRequest = App.ButtonWidth;
_buttonCancel.FontSize = App.FontSizeLarge;
SetMainListView();
}
/// <summary>
/// Sets any options for the main ListView and its header area.
/// </summary>
private void SetMainListView()
{
_gridMainLabels.HeightRequest = App.ButtonHeight;
_gridMainLabels.Padding = new Thickness(App.MarginSize, 0, App.MarginSize, 0);
_labelName.FontSize = App.FontSizeLarge;
_labelDate.FontSize = App.FontSizeLarge;
var gridCols = new ColumnDefinitionCollection
{
new ColumnDefinition {Width = new GridLength(App.ScreenWidth * 0.65f, GridUnitType.Absolute)},
new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}
};
_gridMainLabels.ColumnDefinitions = gridCols;
_listViewMain.RowHeight = (int)(App.ButtonHeight * 0.75f);
_listViewMain.ItemsSource = _gameList;
_listViewMain.ItemTemplate = CreateDgbTemplate(gridCols);
_listViewMain.ItemTapped += ListView_OnItemTapped;
}
/// <summary>
/// Create and return a custom DataTemplate with x number of columns.
/// </summary>
/// <param name="columns">A column collection in either Main or Calculated layout style.</param>
/// <returns></returns>
private DataTemplate CreateDgbTemplate(ColumnDefinitionCollection columns)
{
return new DataTemplate(() =>
{
var grid = new Grid { ColumnDefinitions = columns, Padding = new Thickness(App.MarginSize, 0, App.MarginSize, 0), ColumnSpacing = 5 };
var nameLbl = new Label { FontSize = App.FontSizeMedium, VerticalOptions = LayoutOptions.Center };
nameLbl.SetBinding(Label.TextProperty, "SessionName");
grid.Children.Add(nameLbl, 0, 0);
var tagLbl = new Label { FontSize = App.FontSizeMedium, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
tagLbl.SetBinding(Label.TextProperty, "CreationTime");
grid.Children.Add(tagLbl, 1, 0);
return new ViewCell { View = grid };
});
}
/// <summary>
/// Called when the load button is clicked.
/// Attempts to load the selected game data and closes the load window.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void LoadButton_OnClicked(object sender, EventArgs e)
{
var gi = _listViewMain.SelectedItem as GameInfo;
if (gi == null) return;
App.EnableElements(_buttons, false);
_introPage.StartTagRound(Player.LoadGameSession(gi.SessionName));
await Navigation.PopModalAsync();
App.EnableElements(_buttons, true);
}
/// <summary>
/// Called when the cancel button is clicked.
/// Closes the load game window.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void CancelButton_OnClicked(object sender, EventArgs e)
{
App.EnableElements(_buttons, false);
await Navigation.PopModalAsync();
App.EnableElements(_buttons, true);
}
/// <summary>
/// Called when a ListView item is tapped.
/// Enables the LoadGame Button.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ListView_OnItemTapped(object sender, ItemTappedEventArgs e)
{
if (_listViewMain.SelectedItem != null)
{
_buttonLoad.IsEnabled = true;
_buttonDelete.IsEnabled = true;
}
}
private async void DeleteButton_OnClicked(object sender, EventArgs e)
{
var gi = _listViewMain.SelectedItem as GameInfo;
if (gi == null) return;
App.EnableElements(_buttons, false);
var remove = await DisplayAlert("DELETE SAVED GAME", $"Are you sure you want to permanently delete the saved game \"{gi.SessionName}?", "Delete", "Cancel");
if (!remove) return;
Player.DeleteGameSession(gi.SessionName);
await Navigation.PopModalAsync();
App.EnableElements(_buttons, true);
}
}
}