New OnPlatform/OnIdiom XAML Extension - Usage for Margin Thickness - xaml

In Xamarin.Forms 3.2.0, Xamarin Forms introduced new New OnPlatform/OnIdiom XAML Extension
As per the blog we can re-write the below code,
<Button Text="Extensions" BackgroundColor="Black" TextColor="White">
<Button.HeightRequest>
<OnPlatform x:TypeArguments="x:Double" Default="40">
<On Platform="iOS" Value="60"/>
<On Platform="Android" Value="80"/>
</OnPlatform>
</Button.HeightRequest>
with the new extension.
<Button Text="Extensions" BackgroundColor="Black" TextColor="White"
HeightRequest="{OnPlatform iOS=60, Android=80, Default=40}"/>
Here my doubt is how I can reuse the same OnIdiom XAML Extension for Margin / Thickness.

You should be able to do it like this: <Button Margin="{OnPlatform Android='10,5,10,0', iOS='10,20,10,0'}" />
It's up to you which syntax you like more!

Related

Xamarin.Forms DynamicResource doesn't seem to be working

I can't seem to get a DynamicResource working correctly.
Here's the XAML in App.xml:
<Application.Resources>
<ResourceDictionary>
<Thickness x:Key ="DefaultInsets"
Bottom="4"
Top ="4"
Left ="8"
Right ="8" />
</ResourceDictionary>
</Application.Resources>
And here's what I'm trying to do inside another file's ContentView:
<StackLayout
VerticalOptions="Center"
HeightRequest="225"
Margin="{DynamicResource DefaultInsets}" >
<Entry
x:Name="nameControl"
Placeholder="Full Name"
Margin="{DynamicResource DefaultInsets}"
/>
<Entry
x:Name="passwordControl"
IsPassword="True"
Placeholder="Password"
Margin="{DynamicResource DefaultInsets}" />
</StackLayout>
It seems like this should make consistent insets for the StackLayout from the ContentView, and for the Entry fields from the StackLayout. But I don't see any of that.
What have I done wrong?
Update : I have also tried this with StaticResource, and still no luck.
I use following type with ResourceDictionary. For distinguish, I set the top_margin to 40, here is my screenshot.
Here is my ResourceDictionary.
<Application.Resources>
<ResourceDictionary>
<OnPlatform x:Key="OuterPadding" x:TypeArguments="Thickness">
<On Platform="Android">8 ,40,8,4</On>
<On Platform="iOS">20</On>
<On Platform="WinPhone">24</On>
</OnPlatform>
<!-- left, top, right, and bottom-->
</ResourceDictionary>
</Application.Resources>
Here is my layout.
<StackLayout
VerticalOptions="Center"
HeightRequest="225"
Margin="{DynamicResource OuterMargin}" >
<Entry
x:Name="nameControl"
Placeholder="Full Name"
Margin="{DynamicResource OuterMargin}"
/>
<Entry
x:Name="passwordControl"
IsPassword="True"
Placeholder="Password"
Margin="{DynamicResource OuterMargin}" />
</StackLayout>
Update
I found you layout issue is related to the VerticalOptions="Center" in the StackLayout(If you set the VerticalOptions="Center", then set the margin value is not work).
If I delete it and use StaticResource.
Here is running screenshot(For testing, I change the value of margin top to 20)
Other answers may be valid for some people, but in the end here's what I was doing wrong:
InitializeComponent() was never getting called inside App.xaml.cs.
I had an if-then statement that was always hitting a return before ever getting to InitializeComponent().
When that doesn't get called, App.xaml is inaccessible to the rest of the app, and nothing defined there is available as a DynamicResource.
So I moved InitializeComponent() to happen before the if-then statement, and now it all works like gangbusters.
I hope this helps someone!

Phone and Tablet View for Xamarin.Forms

i'm triying to make a xaml that can be different in phone and tablet. I have something like this:
<OnIdiom x:TypeArguments="View">
<OnIdiom.Phone>
<ContentView VerticalOptions="CenterAndExpand">
...
<LineEntry x:Name="User" Style="{StaticResource Style1}"/>
...
</ContentView>
</OnIdiom.Phone>
<OnIdiom.Tablet>
<ContentView VerticalOptions="End">
...
<LineEntry x:Name="User" Style="{StaticResource Style2}"/>
...
</ContentView>
</OnIdiom.Tablet>
</OnIdiom>
But can't use the same id name in the codebehind. How can i do? i don't want to use 2 variables (for example userPhone and userTablet), for each platform. Is another way to accomplish that? thx!
Most properties on an object can be altered using OnIdiom or OnPlatform.
<Image Aspect="AspectFit" x:Name="logoImg">
<Image.HeightRequest>
<OnPlatform Default="400" Android="350" />
</Image.HeightRequest>
<Image.IsVisible>
<OnIdiom Default="True" Phone="False" />
</Image.IsVisible>
</Image>
So in your example (not tested)
<ContentView>
<ContentView.VerticalOptions>
<OnIdiom Default="End" Phone="CenterAndExpand" />
<ContentView.VerticalOptions>
</ContentView>

Using Font Awesome on Xamarin App shows blank box instead of the icon on UWP

I'm using Font Awesome 5 in my xamarin app. I would like to show an icon in a RadButton (Telerik):
<telerikInput:RadButton
Grid.Row="0" Grid.Column="0"
Text=""
FontSize="30"
Style="{StaticResource TelerikButtonStyle}"
Command="{Binding MyCommand}">
<telerikInput:RadButton.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<On Platform="Android" Value="FontAwesome5Free-Solid-900.otf#Font Awesome 5 Free Solid" />
<On Platform="Windows" Value="Assets/Fonts/FontAwesome5Free-Solid-900.otf#Font Awesome 5 Free Solid" />
</OnPlatform>
</telerikInput:RadButton.FontFamily>
</telerikInput:RadButton>`
For Android, this works fine, but in UWP it shows a blank box.
On Platform should be using "UWP" instead of the ""Windows""
<On Platform="UWP" Value="Assets/Fonts/FontAwesome5Free-Solid-900.otf#Font Awesome 5 Free Solid" />
Font Awesome does not contain Solid in the Font Name. Try removing Solid from the name as below:
<On Platform="Windows" Value="Assets/Fonts/FontAwesome5Free-Solid-900.otf#Font Awesome 5 Free" />
EDIT:
If you are using Xamarin.Forms 2.3.4 or greater than replace Windows with UWP as below:
<On Platform="UWP" Value="Assets/Fonts/FontAwesome5Free-Solid-900.otf#Font Awesome 5 Free" />
I have tried this in blank solution and got it working as follows:
Added the font in the Assets/Fonts folder in UWP project and made sure it has the correct name (in my case I renamed the font to FontAwesome5.otf) and Build Action of Content:
Used the following to reference the font (note - this sample only sets UWP path, so you should add the other platforms as in your question):
XAML:
<Label Text=""
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<On Platform="UWP" Value="Assets/Fonts/FontAwesome5.otf#Font Awesome 5 Free" />
</OnPlatform>
</Label.FontFamily>
</Label>
The proper # suffix can be found out using some font viewer apps, like dp4 Font Viewer:
Result:

UWPCommunityToolkit DropShadowPanel on Button

I'm trying to apply a shadow effect on a button on a UWP application.
I'm using the UWPCommunityToolkit tool and the control DropShadowPanel. Here an example :
http://www.uwpcommunitytoolkit.com/en/master/controls/DropShadowPanel/
So my code for apply on a button control :
<controls:DropShadowPanel BlurRadius="{Binding BlurRadius.Value, Mode=OneWay}"
ShadowOpacity="{Binding Opacity.Value, Mode=OneWay}"
OffsetX="{Binding OffsetX.Value, Mode=OneWay}"
OffsetY="{Binding OffsetY.Value, Mode=OneWay}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Button Content="My button" />
</controls:DropShadowPanel>
But the result is :
The shadow cover all my button control.
According to the doc Button control doesn't directy inherit from FrameworkElement, that is maybe a reason.
Regards
Hum problem solved by using custom values :
<controls:DropShadowPanel BlurRadius="4.0"
ShadowOpacity="0.70"
OffsetX="5.0"
OffsetY="5.0"
Color="Black"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Button Content="My button" Background="Aqua" />
</controls:DropShadowPanel>

XAML Xamarin OnPlatform Binding

I think my code is self explanatory:
<Label Style="{DynamicResource labelStyle}"
HorizontalTextAlignment="End" Text="{Binding message}">
<OnPlatform x:TypeArguments="Color">
<OnPlatform.iOS>
{DynamicResource rightBubbleFontColor}
</OnPlatform.iOS>
<OnPlatform.Android>
{DynamicResource rightBubbleFontColor}
</OnPlatform.Android>
<OnPlatform.Android>
{StaticResource rightBubbleFontColor}
</OnPlatform.Android>
</OnPlatform>
</Label>
I'm trying to dynamically bind a color to the label. Depending on the current platform, it has to be another type of resource (DynamicResource or StaticResource).
I get this exception when trying to build the solution:
System.ArgumentException: An item with the same key has already been added.
UPDATE
I now have this code:
<Label Style="{DynamicResource labelStyle}"
HorizontalTextAlignment="End" Text="{Binding message}">
<Label.TextColor>
<OnPlatform
x:Key="RightBubbleFontColor"
x:TypeArguments="Color"
iOS="{DynamicResource rightBubbleFontColor}"
Android="{DynamicResource rightBubbleFontColor}"
WinPhone="{StaticResource rightBubbleFontColor}">
</OnPlatform>
</Label.TextColor>
</Label>
And I get the following error message:
Object reference not set to an instance of an object.
When I replace the binding to a color it works.
Working example:
<Label Style="{DynamicResource labelStyle}"
HorizontalTextAlignment="End" Text="{Binding message}">
<Label.TextColor>
<OnPlatform
x:Key="RightBubbleFontColor"
x:TypeArguments="Color"
iOS="Red"
Android="Green"
WinPhone="Blue">
</OnPlatform>
</Label.TextColor>
</Label>
So it has to be an issue with the way I'm trying to bind this I guess.
EDIT
Asked a new question to describe the problem better: https://stackoverflow.com/questions/39852888/xamarin-forms-use-dynamicresource-or-staticresource-depending-on-os
You have two <OnPlatform.Android> elements. I'm assuming the last would be <OnPlatform.WinPhone>.
EDITED
Now that you have that fixed, maybe try this for it to actually work?
<OnPlatform
x:Key="BubbleTextColor"
x:TypedArguments="Color"
iOS="{DynamicResource rightBubbleFontColor}"
Android="{DynamicResource rightBubbleFontColor}"
WinPhone="{StaticResource rightBubbleFontColor}" />
Then bind it where necessary.
Not sure if it will work any differently than what you already have, but I guess it's worth a shot.