@ -0,0 +1,86 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<ContentView | |||||
xmlns="http://xamarin.com/schemas/2014/forms" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |||||
x:Class="eShopOnContainers.Core.Controls.CartButton"> | |||||
<ContentView.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="AddButtonStyle" | |||||
TargetType="{x:Type Grid}"> | |||||
<Setter Property="HeightRequest" | |||||
Value="42" /> | |||||
<Setter Property="WidthRequest" | |||||
Value="42" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="End" /> | |||||
<Setter Property="Margin" | |||||
Value="0, 0, 0, 24" /> | |||||
</Style> | |||||
<Style x:Key="AddBackgroundImageStyle" | |||||
TargetType="{x:Type Image}"> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="HeightRequest" | |||||
Value="128" /> | |||||
<Setter Property="WidthRequest" | |||||
Value="128" /> | |||||
</Style> | |||||
<Style x:Key="AddImageStyle" | |||||
TargetType="{x:Type Image}"> | |||||
<Setter Property="HeightRequest" | |||||
Value="24" /> | |||||
<Setter Property="WidthRequest" | |||||
Value="24" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</ContentView.Resources> | |||||
<ContentView.Content> | |||||
<Grid> | |||||
<!-- IOS & ANDROID --> | |||||
<Grid | |||||
Style="{StaticResource AddButtonStyle}"> | |||||
<Grid.IsVisible> | |||||
<OnPlatform | |||||
x:TypeArguments="x:Boolean" | |||||
Android="True" | |||||
iOS="True" | |||||
WinPhone="False"/> | |||||
</Grid.IsVisible> | |||||
<BoxView | |||||
BackgroundColor="{StaticResource LightGreenColor}" | |||||
StyleClass="Circle" /> | |||||
<Image | |||||
Aspect="AspectFit" | |||||
Source="product_add" | |||||
Style="{StaticResource AddImageStyle}"> | |||||
<Image.Margin> | |||||
<OnPlatform | |||||
x:TypeArguments="Thickness" | |||||
Android="5, 12, 12, 12" | |||||
iOS="6, 12, 12, 12"/> | |||||
</Image.Margin> | |||||
</Image> | |||||
</Grid> | |||||
<!-- UWP --> | |||||
<Grid> | |||||
<Image | |||||
Source="Assets/circle_button_background.png" | |||||
Aspect="AspectFit" | |||||
Style="{StaticResource AddBackgroundImageStyle}" /> | |||||
<Image | |||||
Aspect="AspectFit" | |||||
Source="Assets\product_add.png" | |||||
Style="{StaticResource AddImageStyle}" | |||||
Margin="12" /> | |||||
</Grid> | |||||
</Grid> | |||||
</ContentView.Content> | |||||
</ContentView> |
@ -0,0 +1,12 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Controls | |||||
{ | |||||
public partial class CartButton : ContentView | |||||
{ | |||||
public CartButton() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Controls | |||||
{ | |||||
public class CustomSwitch : Switch | |||||
{ | |||||
public static readonly BindableProperty TextOnProperty = BindableProperty.Create("TextOn", | |||||
typeof(string), typeof(CustomSwitch), string.Empty); | |||||
public static readonly BindableProperty TextOffProperty = BindableProperty.Create("TextOff", | |||||
typeof(string), typeof(CustomSwitch), string.Empty); | |||||
public string TextOn | |||||
{ | |||||
get { return (string)this.GetValue(TextOnProperty); } | |||||
set { this.SetValue(TextOnProperty, value); } | |||||
} | |||||
public string TextOff | |||||
{ | |||||
get { return (string)this.GetValue(TextOffProperty); } | |||||
set { this.SetValue(TextOffProperty, value); } | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,9 @@ | |||||
using eShopOnContainers.ViewModels.Base; | |||||
namespace eShopOnContainers.Core.ViewModels | |||||
{ | |||||
public class SettingsViewModel : ViewModelBase | |||||
{ | |||||
} | |||||
} |
@ -0,0 +1,86 @@ | |||||
<?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="eShopOnContainers.Core.Views.SettingsView" | |||||
xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core" | |||||
Title="Settings"> | |||||
<ContentPage.Resources> | |||||
<ResourceDictionary> | |||||
<Style x:Key="SettingsTitleStyle" | |||||
TargetType="{x:Type Label}"> | |||||
<Setter Property="FontFamily" | |||||
Value="{StaticResource MontserratRegular}" /> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource MediumSize}" /> | |||||
<Setter Property="HorizontalOptions" | |||||
Value="Start" /> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
<Setter Property="Margin" | |||||
Value="12, 0" /> | |||||
</Style> | |||||
<Style x:Key="SettingsDescriptionStyle" | |||||
TargetType="{x:Type Label}" | |||||
BasedOn="{StaticResource SettingsTitleStyle}"> | |||||
<Setter Property="FontSize" | |||||
Value="{StaticResource LittleSize}" /> | |||||
</Style> | |||||
<Style x:Key="SettingsSwitchStyle" | |||||
TargetType="{x:Type controls:CustomSwitch}"> | |||||
<Setter Property="VerticalOptions" | |||||
Value="Center" /> | |||||
</Style> | |||||
</ResourceDictionary> | |||||
</ContentPage.Resources> | |||||
<Grid | |||||
BackgroundColor="{StaticResource BackgroundColor}"> | |||||
<!-- SETTINGS --> | |||||
<ScrollView> | |||||
<StackLayout> | |||||
<!-- MOCK SERVICES --> | |||||
<Grid> | |||||
<Grid.ColumnDefinitions> | |||||
<ColumnDefinition Width="*" /> | |||||
<ColumnDefinition Width="Auto" /> | |||||
</Grid.ColumnDefinitions> | |||||
<Grid.RowDefinitions> | |||||
<RowDefinition Height="1" /> | |||||
<RowDefinition Height="Auto" /> | |||||
<RowDefinition Height="1" /> | |||||
</Grid.RowDefinitions> | |||||
<Grid | |||||
Grid.Row="0" | |||||
Grid.Column="0" | |||||
Grid.ColumnSpan="2" | |||||
BackgroundColor="Gray"/> | |||||
<StackLayout | |||||
Grid.Column="0" | |||||
Grid.Row="1"> | |||||
<Label | |||||
Text="Use Mock Services" | |||||
TextColor="{StaticResource GreenColor}" | |||||
Style="{StaticResource SettingsTitleStyle}"/> | |||||
<Label | |||||
Text="Mock Services are simulated objects that mimic the behavior of real services in controlled ways" | |||||
Style="{StaticResource SettingsDescriptionStyle}"/> | |||||
</StackLayout> | |||||
<controls:CustomSwitch | |||||
TextOn="Mock" | |||||
TextOff="Azure" | |||||
Grid.Column="1" | |||||
Grid.Row="1" | |||||
Style="{StaticResource SettingsSwitchStyle}"/> | |||||
<Grid | |||||
Grid.Row="2" | |||||
Grid.Column="0" | |||||
Grid.ColumnSpan="2" | |||||
BackgroundColor="Gray"/> | |||||
</Grid> | |||||
</StackLayout> | |||||
</ScrollView> | |||||
</Grid> | |||||
</ContentPage> |
@ -0,0 +1,18 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Xamarin.Forms; | |||||
namespace eShopOnContainers.Core.Views | |||||
{ | |||||
public partial class SettingsView : ContentPage | |||||
{ | |||||
public SettingsView() | |||||
{ | |||||
InitializeComponent(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,58 @@ | |||||
using System; | |||||
using Xamarin.Forms.Platform.Android; | |||||
using Xamarin.Forms; | |||||
using eShopOnContainers.Core.Controls; | |||||
namespace eShopOnContainers.Droid.Renderers | |||||
{ | |||||
public class CustomSwitchRenderer : ViewRenderer<CustomSwitch, Android.Widget.Switch> | |||||
{ | |||||
protected override void OnElementChanged(ElementChangedEventArgs<CustomSwitch> e) | |||||
{ | |||||
base.OnElementChanged(e); | |||||
if (e.OldElement != null) | |||||
{ | |||||
this.Element.Toggled -= ElementToggled; | |||||
return; | |||||
} | |||||
if (this.Element == null) | |||||
{ | |||||
return; | |||||
} | |||||
var switchControl = new Android.Widget.Switch(Forms.Context) | |||||
{ | |||||
TextOn = this.Element.TextOn, | |||||
TextOff = this.Element.TextOff | |||||
}; | |||||
switchControl.CheckedChange += ControlValueChanged; | |||||
this.Element.Toggled += ElementToggled; | |||||
this.SetNativeControl(switchControl); | |||||
} | |||||
protected override void Dispose(bool disposing) | |||||
{ | |||||
if (disposing) | |||||
{ | |||||
this.Control.CheckedChange -= this.ControlValueChanged; | |||||
this.Element.Toggled -= ElementToggled; | |||||
} | |||||
base.Dispose(disposing); | |||||
} | |||||
private void ElementToggled(object sender, ToggledEventArgs e) | |||||
{ | |||||
this.Control.Checked = this.Element.IsToggled; | |||||
} | |||||
private void ControlValueChanged(object sender, EventArgs e) | |||||
{ | |||||
this.Element.IsToggled = this.Control.Checked; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,60 @@ | |||||
using eShopOnContainers.Core.Controls; | |||||
using eShopOnContainers.Windows.Renderers; | |||||
using Windows.UI.Xaml.Controls; | |||||
using Xamarin.Forms; | |||||
using Xamarin.Forms.Platform.UWP; | |||||
[assembly: ExportRenderer(typeof(CustomSwitch), typeof(CustomSwitchRenderer))] | |||||
namespace eShopOnContainers.Windows.Renderers | |||||
{ | |||||
public class CustomSwitchRenderer : ViewRenderer<CustomSwitch, ToggleSwitch> | |||||
{ | |||||
protected override void OnElementChanged(ElementChangedEventArgs<CustomSwitch> e) | |||||
{ | |||||
base.OnElementChanged(e); | |||||
if (this.Element == null) | |||||
{ | |||||
return; | |||||
} | |||||
if (e.OldElement != null) | |||||
{ | |||||
this.Element.Toggled -= ElementToggled; | |||||
return; | |||||
} | |||||
var toggleSwitchControl = new ToggleSwitch | |||||
{ | |||||
OnContent = this.Element.TextOn, | |||||
OffContent = this.Element.TextOff | |||||
}; | |||||
toggleSwitchControl.Toggled += ControlToggled; | |||||
this.Element.Toggled += ElementToggled; | |||||
this.SetNativeControl(toggleSwitchControl); | |||||
} | |||||
protected override void Dispose(bool disposing) | |||||
{ | |||||
if (disposing) | |||||
{ | |||||
this.Control.Toggled -= this.ControlToggled; | |||||
this.Element.Toggled -= ElementToggled; | |||||
} | |||||
base.Dispose(disposing); | |||||
} | |||||
private void ElementToggled(object sender, ToggledEventArgs e) | |||||
{ | |||||
this.Control.IsOn = this.Element.IsToggled; | |||||
} | |||||
private void ControlToggled(object sender, global::Windows.UI.Xaml.RoutedEventArgs e) | |||||
{ | |||||
this.Element.IsToggled = this.Control.IsOn; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,56 @@ | |||||
using eShopOnContainers.Core.Controls; | |||||
using eShopOnContainers.iOS.Renderers; | |||||
using UIKit; | |||||
using Xamarin.Forms; | |||||
using Xamarin.Forms.Platform.iOS; | |||||
[assembly: ExportRenderer(typeof(CustomSwitch), typeof(CustomSwitchRenderer))] | |||||
namespace eShopOnContainers.iOS.Renderers | |||||
{ | |||||
public class CustomSwitchRenderer : ViewRenderer<CustomSwitch, UISwitch> | |||||
{ | |||||
protected override void OnElementChanged(ElementChangedEventArgs<CustomSwitch> e) | |||||
{ | |||||
base.OnElementChanged(e); | |||||
if (e.OldElement != null) | |||||
{ | |||||
this.Element.Toggled -= ElementToggled; | |||||
return; | |||||
} | |||||
if (this.Element == null) | |||||
{ | |||||
return; | |||||
} | |||||
var uiSwitchControl = new UISwitch(); | |||||
uiSwitchControl.ValueChanged += ControlValueChanged; | |||||
this.Element.Toggled += ElementToggled; | |||||
this.SetNativeControl(uiSwitchControl); | |||||
} | |||||
protected override void Dispose(bool disposing) | |||||
{ | |||||
if (disposing) | |||||
{ | |||||
this.Control.ValueChanged -= this.ControlValueChanged; | |||||
this.Element.Toggled -= ElementToggled; | |||||
} | |||||
base.Dispose(disposing); | |||||
} | |||||
private void ElementToggled(object sender, ToggledEventArgs e) | |||||
{ | |||||
this.Control.On = Element.IsToggled; | |||||
} | |||||
private void ControlValueChanged(object sender, System.EventArgs e) | |||||
{ | |||||
this.Element.IsToggled = this.Control.On; | |||||
} | |||||
} | |||||
} |
@ -1,10 +1,110 @@ | |||||
using Foundation; | |||||
using eShopOnContainers.Core.Controls; | |||||
using eShopOnContainers.iOS.Renderers; | |||||
using Foundation; | |||||
using System.Threading.Tasks; | |||||
using UIKit; | |||||
using Xamarin.Forms; | |||||
using Xamarin.Forms.Platform.iOS; | using Xamarin.Forms.Platform.iOS; | ||||
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))] | |||||
namespace eShopOnContainers.iOS.Renderers | namespace eShopOnContainers.iOS.Renderers | ||||
{ | { | ||||
[Preserve] | [Preserve] | ||||
public class CustomTabbedPageRenderer : TabbedRenderer | public class CustomTabbedPageRenderer : TabbedRenderer | ||||
{ | { | ||||
public override void ViewWillAppear(bool animated) | |||||
{ | |||||
base.ViewWillAppear(animated); | |||||
for (var i = 0; i < TabBar.Items.Length; i++) | |||||
{ | |||||
AddTabBadge(i); | |||||
} | |||||
Element.ChildAdded += OnTabAdded; | |||||
Element.ChildRemoved += OnTabRemoved; | |||||
} | |||||
private void AddTabBadge(int tabIndex) | |||||
{ | |||||
var element = Tabbed.Children[tabIndex]; | |||||
element.PropertyChanged += OnTabbedPagePropertyChanged; | |||||
if (TabBar.Items.Length > tabIndex) | |||||
{ | |||||
var tabBarItem = TabBar.Items[tabIndex]; | |||||
UpdateTabBadgeText(tabBarItem, element); | |||||
var tabColor = CustomTabbedPage.GetBadgeColor(element); | |||||
if (tabColor != Color.Default) | |||||
{ | |||||
tabBarItem.BadgeColor = tabColor.ToUIColor(); | |||||
} | |||||
} | |||||
} | |||||
private void UpdateTabBadgeText(UITabBarItem tabBarItem, Element element) | |||||
{ | |||||
var text = CustomTabbedPage.GetBadgeText(element); | |||||
tabBarItem.BadgeValue = string.IsNullOrEmpty(text) ? null : text; | |||||
} | |||||
private void OnTabbedPagePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) | |||||
{ | |||||
var page = sender as Page; | |||||
if (page == null) | |||||
return; | |||||
if (e.PropertyName == CustomTabbedPage.BadgeTextProperty.PropertyName) | |||||
{ | |||||
var tabIndex = Tabbed.Children.IndexOf(page); | |||||
if (tabIndex < TabBar.Items.Length) | |||||
UpdateTabBadgeText(TabBar.Items[tabIndex], page); | |||||
return; | |||||
} | |||||
if (e.PropertyName == CustomTabbedPage.BadgeColorProperty.PropertyName) | |||||
{ | |||||
var tabIndex = Tabbed.Children.IndexOf(page); | |||||
if (tabIndex < TabBar.Items.Length) | |||||
TabBar.Items[tabIndex].BadgeColor = CustomTabbedPage.GetBadgeColor(page).ToUIColor(); | |||||
} | |||||
} | |||||
private async void OnTabAdded(object sender, ElementEventArgs e) | |||||
{ | |||||
await Task.Delay(10); | |||||
var page = e.Element as Page; | |||||
if (page == null) | |||||
return; | |||||
var tabIndex = Tabbed.Children.IndexOf(page); | |||||
AddTabBadge(tabIndex); | |||||
} | |||||
private void OnTabRemoved(object sender, ElementEventArgs e) | |||||
{ | |||||
e.Element.PropertyChanged -= OnTabbedPagePropertyChanged; | |||||
} | |||||
protected override void Dispose(bool disposing) | |||||
{ | |||||
if (Tabbed != null) | |||||
{ | |||||
foreach (var tab in Tabbed.Children) | |||||
{ | |||||
tab.PropertyChanged -= OnTabbedPagePropertyChanged; | |||||
} | |||||
Tabbed.ChildAdded -= OnTabAdded; | |||||
Tabbed.ChildRemoved -= OnTabRemoved; | |||||
} | |||||
base.Dispose(disposing); | |||||
} | |||||
} | } | ||||
} | |||||
} |
@ -0,0 +1,68 @@ | |||||
using System; | |||||
using CoreGraphics; | |||||
using eShopOnContainers.Core.Views; | |||||
using eShopOnContainers.iOS; | |||||
using SlideOverKit.iOS; | |||||
using UIKit; | |||||
using Xamarin.Forms; | |||||
using Xamarin.Forms.Platform.iOS; | |||||
[assembly: ExportRenderer(typeof(CatalogView), typeof(SlideDownMenuPageRenderer))] | |||||
namespace eShopOnContainers.iOS | |||||
{ | |||||
public class SlideDownMenuPageRenderer : PageRenderer, ISlideOverKitPageRendereriOS | |||||
{ | |||||
public Action<bool> ViewDidAppearEvent { get; set; } | |||||
public Action<VisualElementChangedEventArgs> OnElementChangedEvent { get; set; } | |||||
public Action ViewDidLayoutSubviewsEvent { get; set; } | |||||
public Action<bool> ViewDidDisappearEvent { get; set; } | |||||
public Action<CGSize, IUIViewControllerTransitionCoordinator> ViewWillTransitionToSizeEvent { get; set; } | |||||
public SlideDownMenuPageRenderer() | |||||
{ | |||||
new SlideOverKitiOSHandler().Init(this); | |||||
} | |||||
protected override void OnElementChanged(VisualElementChangedEventArgs e) | |||||
{ | |||||
base.OnElementChanged(e); | |||||
if (OnElementChangedEvent != null) | |||||
OnElementChangedEvent(e); | |||||
} | |||||
public override void ViewDidLayoutSubviews() | |||||
{ | |||||
base.ViewDidLayoutSubviews(); | |||||
if (ViewDidLayoutSubviewsEvent != null) | |||||
ViewDidLayoutSubviewsEvent(); | |||||
} | |||||
public override void ViewDidAppear(bool animated) | |||||
{ | |||||
base.ViewDidAppear(animated); | |||||
if (ViewDidAppearEvent != null) | |||||
ViewDidAppearEvent(animated); | |||||
} | |||||
public override void ViewDidDisappear(bool animated) | |||||
{ | |||||
base.ViewDidDisappear(animated); | |||||
if (ViewDidDisappearEvent != null) | |||||
ViewDidDisappearEvent(animated); | |||||
} | |||||
public override void ViewWillTransitionToSize(CGSize toSize, IUIViewControllerTransitionCoordinator coordinator) | |||||
{ | |||||
base.ViewWillTransitionToSize(toSize, coordinator); | |||||
if (ViewWillTransitionToSizeEvent != null) | |||||
ViewWillTransitionToSizeEvent(toSize, coordinator); | |||||
} | |||||
} | |||||
} |