@ -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; | |||
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))] | |||
namespace eShopOnContainers.iOS.Renderers | |||
{ | |||
[Preserve] | |||
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); | |||
} | |||
} | |||
} |