Mais conteúdo relacionado Semelhante a Native cross-platform mobile apps with C# and Xamarin.Forms (20) Native cross-platform mobile apps with C# and Xamarin.Forms7. What is Xamarin NOT?
Write once, run anywhere UI
Replacement for learning about each platform
8. Xamarin - iOS
AOT compiled
to ARM assembly
Mono framework included
Exposes CocoaTouch SDK
10. Xamarin - Windows Phone
Compiled to IL
Uses built in phone runtime
No Mono / Xamarin SDK required
11. - Can I use my favorite SDK?
Yes
- Can I use my favorite Nuget package?
Sometimes
FAQ
12. - Are apps slower than native?
About the same *
- Are apps bigger than native?
Yes
FAQ
* https://medium.com/@harrycheung/mobile-app-performance-redux-e512be94f976
13. - Can I use async / await?
Yes
- Can I use “xyz” feature of .NET?
Yes *
FAQ
17. - WPF? Forms will be familiar.
- Develop by feature, not by platform
Xamarin Forms
18. Forms?
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage x:Class="EntryTest.Login">
<ContentPage.Content>
<StackLayout WidthRequest="200"
HorizontalOptions="Center"
VerticalOptions="Center">
<Entry Placeholder="Username" />
<Entry Placeholder="Password" />
<Button Text="Login"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
19. XAML or code
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage x:Class="EntryTest.Login">
<ContentPage.Content>
<StackLayout WidthRequest="200"
HorizontalOptions="Center"
VerticalOptions="Center">
<Entry Placeholder="Username" />
<Entry Placeholder="Password" />
<Button Text="Login"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
var page = new ContentPage
{
Content = new StackLayout
{
WidthRequest = 200,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Children =
{
new Entry { Placeholder = "Username" },
new Entry { Placeholder = "Password" },
new Button { Text = "Login" }
}
}
};
23. Customization - Style
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="TextColor" Value="Black" />
<Setter Property="BorderWidth" Value="1" />
<Setter Property="BorderRadius" Value="3" />
<Setter Property="BackgroundColor" Value="{StaticResource ButtonBackgroundColor}" />
<Setter Property="BorderColor" Value="{StaticResource ButtonBorderColor}" />
<Setter Property="Font" Value="{StaticResource ButtonFont}" />
<Style.Triggers>
<Trigger Property="controls:ButtonExtensions.IsPrimary" Value="True" TargetType="Button">
<Setter Property="BackgroundColor" Value="{StaticResource PrimaryBackgroundColor}" />
<Setter Property="BorderColor" Value="{StaticResource PrimaryBorderColor}" />
</Trigger>
</Style.Triggers>
</Style>
24. Customization - Renderer
public class StandardEntryRenderer : EntryRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged (e);
if (e.OldElement == null) {
AddBorderToControl ();
Control.Started += (sender, args) => Control.Layer.BorderColor = YellowBorderColor.CGColor;
Control.Ended += (sender, args) => Control.Layer.BorderColor = GreyBorderColor.CGColor;
}
}
void AddBorderToControl()
{
Control.Layer.CornerRadius = 3;
Control.Layer.BorderWidth = 1;
Control.Layer.BorderColor = GreyBorderColor.CGColor;
}
}
25. Customization - Renderer
public class PullToRefreshViewRenderer : VisualElementRenderer<PullToRefreshView>
{
UIRefreshControl refreshControl;
protected override void OnElementChanged(ElementChangedEventArgs<PullToRefreshView> e)
{
base.OnElementChanged (e);
var renderer = Subviews [0] as ListViewRenderer;
if (renderer == null)
return;
refreshControl = new UIRefreshControl ();
refreshControl.ValueChanged += OnRefreshingChanged;
renderer.Control.AddSubview(refreshControl);
UpdateIsRefreshing();
}
}
26. Customization - per-platform
<OnPlatform x:TypeArguments="Font"
Android="sans-serif,None,21"
iOS="HelveticaNeue,None,16"
x:Key="TitleFont"/>
<Style x:Key="TitleLabel" TargetType="Label">
<Setter Property="AbsoluteLayout.LayoutBounds" Value="0,0,AutoSize,AutoSize" />
<Setter Property="AbsoluteLayout.LayoutFlags" Value="PositionProportional" />
<Setter Property="Font" Value="{StaticResource TitleFont}" />
<Setter Property="TextColor" Value="#333" />
</Style>
27. MVVM
<StackLayout>
<Entry Text="{Binding Username}"/>
<Entry Text="{Binding Password}"/>
<Button Text="Login"
Command="{Binding LoginCommand}"/>
</StackLayout>
public class LoginViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Command LoginCommand { get; private set; }
string _username;
public string Username
{
get { return _username; }
set {
_username = value;
NotifyPropertyChanged(); }
}
// continued…
}
28. Attached Properties / Triggers
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="TextColor" Value="Black" />
<Setter Property="BorderWidth" Value="1" />
<Setter Property="BorderRadius" Value="3" />
<Setter Property="BackgroundColor" Value="{StaticResource ButtonBackgroundColor}" />
<Setter Property="BorderColor" Value="{StaticResource ButtonBorderColor}" />
<Setter Property="Font" Value="{StaticResource ButtonFont}" />
<Style.Triggers>
<Trigger Property="controls:ButtonExtensions.IsPrimary" Value="True" TargetType="Button">
<Setter Property="BackgroundColor" Value="{StaticResource PrimaryBackgroundColor}" />
<Setter Property="BorderColor" Value="{StaticResource PrimaryBorderColor}" />
</Trigger>
</Style.Triggers>
</Style>
29. Behaviors
<Entry Placeholder="Enter a System.Double">
<Entry.Behaviors>
<local:NumericValidationBehavior />
</Entry.Behaviors>
</Entry>
public class NumericValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
double result;
bool isValid = Double.TryParse (args.NewTextValue, out result);
((Entry)sender).TextColor = isValid ? Color.Default : Color.Red;
}
}
31. - Are XF apps slower than native?
Yes
- Are XF apps bigger than native?
Yes
Speed / size redux
32. - New or Existing product?
- New or Existing team?
- Resources vs user experience
Should I use XF?
34. - One UI layout
- Very customizable
- Initial customization investment
- Develop by feature
- Very active development
Good
35. - Bugs, fix with renderers
- Renderers have “internal” code
- No XAML designer
- Open source?
Bad
Notas do Editor Background: .NET / WPF / AngularJS
Xamarin: 8 months ago
Forms: 6 months ago
Ordertracker: Customer - where is my order / Restaurant - where are my drivers iOS
exposes CocoaTouch SDK (ex. UIKit)
Android
exposes Android SDK
interacts with native types via JNI
most of Mono.Android is just wrappers
Native / Siloed
Language / UI / Container
Abandoned: Facebook / LinkedIn
Problems: debugging, performance, animation
Combination: Instagram - timeline, JUST EAT - checkout
Cordova provides an abstraction over OS services like location Makes cross-platform applications easier No JIT interacts with native types via JNI
most of Mono.Android is just wrappers SDK: Google Analytics / AWS-SDK
iOS: binaries (.a) / headers (.h) + bindings
Android: .jar + bindings
Nuget: Autofac / JSON.Net
PCL or Android/iOS specific C# code iOS: C++ / Swift faster , Objective-C slower
Android: C++ faster , Davlik same
Frameworks
iOS - generics special case
Xamarin Forms, a bit more so too. Dynamic Runtime Language - NO
Generics - Of Course!
iOS: storyboard, xib
Android: layouts, drawables, styles
WP: xaml
iOS: storyboard, xib
Android: layouts, drawables, styles
WP: xaml
iOS: storyboard, xib
Android: layouts, drawables, styles
WP: xaml
Variation of patterns like MVC / MVP
VM is a dataconverter between the view and model
Goal is to remove all “code-behind” from .NET (WPF) Forms
Variation of patterns like MVC / MVP
VM is a dataconverter between the view and model
Goal is to remove all “code-behind” from .NET (WPF) Forms DS:
Service Locator pattern
Static singleton (again)
No constructor injection
MC:
Used internally by XF
Static singleton
Strange generic syntax
For new team:
start simple
gain platform experience
mix experienced with non-experienced
code sharing vs custom UI