Xamarin Forms OnPlatform in Xaml - xaml

I have the following C# code:
var footer = new StackLayout()
{ BackgroundColor = Device.OnPlatform(Color.FromRgb(225, 240, 251), Color.FromRgb(225, 240, 251), Color.Black),
};
How can I translate that into Xamarin Xaml, more importantly the Device Platform specifics for the FromRgb?
I have the following XAML so far... again, it's the FromRgb that's stumping me.
<StackLayout.BackgroundColor>
<Color>
<OnPlatform x:TypeArguments="Color"></OnPlatform>
</Color>
</StackLayout.BackgroundColor>
UPDATE 14/02/2015
I've just tried the answer below and I have the following but it's not updating the background colour for either iOS or Windows Phone. If I add the Background Color to the root StackLayout element it works...:
<StackLayout HorizontalOptions="FillAndExpand">
<StackLayout.BackgroundColor>
<Color>
<OnPlatform x:TypeArguments="Color">
<OnPlatform.WinPhone>#51C0D4</OnPlatform.WinPhone>
<OnPlatform.iOS>#51C0D4</OnPlatform.iOS>
</OnPlatform>
</Color>
</StackLayout.BackgroundColor>
<Label Text=""></Label>
<StackLayout Orientation="Horizontal" VerticalOptions="EndAndExpand" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
<Button Text="Login"></Button>
<Button Text="Sign Up"></Button>
</StackLayout>
</StackLayout>
</StackLayout>

You're almost there. The default converter takes care of converting the color from either a named color (e.g. White, Red, etc.) or a hex color (e.g.: #FF0000).
<StackLayout.BackgroundColor>
<OnPlatform x:TypeArguments="Color">
<OnPlatform.iOS>#FF0000</OnPlatform.iOS>
<OnPlatform.Android>#00FF00</OnPlatform.Android>
</OnPlatform>
</StackLayout.BackgroundColor>

Newer version syntax of OnPlatform is slightly different
In Xaml:
<ResourceDictionary>
<OnPlatform x:Key="SwitchOnColor" x:TypeArguments="Color" >
<On Platform="iOS|Android" >#0000FF</On>
<On Platform="UWP">#FF0000</On>
</OnPlatform>
</ResourceDictionary>
In code:
switch (Device.RuntimePlatform)
{
case "iOS":
break;
case "Android":
break;
case "UWP":
break;
default:
break;
}

You can do this also:
<ContentView>
<OnPlatform x:TypeArguments="View">
<On Platform="iOS">
<Label Text="iOS" />
</On>
<On Platform="Android">
<Label Text="Android" />
</On>
</OnPlatform>
</ContentView>

Related

AbsoluteLayout.LayoutBounds doens´t work after I updated to Xamarin.Forms 5.0

After I updated to Xamarin.Forms 5.0 this line of code has been broken:
<AbsoluteLayout.LayoutBounds>
<OnPlatform x:TypeArguments="Rectangle">
<On Platform="Android">0.5,0.49,0.4,0.5</On>
<On Platform="iOS">0.5,0.52,0.4,0.5</On>
</OnPlatform>
</AbsoluteLayout.LayoutBounds>
What can I do to fix it?
About setting AbsoluteLayout.LayoutBounds by platform, you can try to following code:
<AbsoluteLayout Margin="20">
<BoxView AbsoluteLayout.LayoutBounds="{OnPlatform Android='0,10,200,5', iOS='0,0,.5,.5'}" Color="Silver">
</BoxView>
</AbsoluteLayout>

Using OnIdiom with AbsoluteLayout

I have circular buttons and am trying to change the size of them depending on if they are on phone or tablet using AbsolutLayout.
Here is my xaml:
<Frame BackgroundColor="{StaticResource ThemeColor}" Padding="0" CornerRadius="40" AbsoluteLayout.LayoutBounds="{StaticResource HomeCircle}" AbsoluteLayout.LayoutFlags="PositionProportional">
<Label Text="" HorizontalOptions="Center" VerticalOptions="Center" Style="{StaticResource Icon}" TextColor="{StaticResource LabelColor}"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="Directions"/>
</Frame.GestureRecognizers>
</Frame>
<AbsoluteLayout.Resources>
<ResourceDictionary>
<OnIdiom x:Key="HomeCircle" x:TypeArguments="Frame" Phone=".85,.375, 80, 80"
Tablet=".85,.375, 120, 120"/>
</ResourceDictionary>
</AbsoluteLayout.Resources>
I looked at this resource and it did not work:
How to use attached properties such as Grid.Row, AbsoluteLayout.LayoutFlags to OnPlatform tag in Xamarin Forms
Edit: Have tried TypeArguments of Rectangle, AbsoluteLayout, and Frame and they all give this error:
Error XFC0009 No property, BindableProperty, or event found for "Phone", or mismatching type between value and property.
Edit: Have also looked at this thread and it provides the same error:
https://xamarin.github.io/bugzilla-archives/55/55183/bug.html
I faced the same problem in the past. My solution is to set the AbsoluteLayout bounds by Binding in place of StaticResource.
In the ViewModel:
public Xamarin.Forms.Rectangle HomeCircle => Xamarin.Forms.Device.Idiom == TargetIdiom.Phone ? new Xamarin.Forms.Rectangle(0.5f, 0.5f, 80, 80) : new Xamarin.Forms.Rectangle(0.5f, 0.5f, 120, 120);
In the yaml:
<AbsoluteLayout>
<Frame BackgroundColor="Gray"
Padding="0"
CornerRadius="40"
AbsoluteLayout.LayoutBounds="{Binding HomeCircle}"
AbsoluteLayout.LayoutFlags="PositionProportional">
<Label Text="TEST"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="Black"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding DoSomething}"/>
</Frame.GestureRecognizers>
</Frame>
</AbsoluteLayout>
Anyway AbsoluteLayout.LayoutBounds requires Rectangle, and markup doesn't always allow everything :)

How to make a Floating Action Button in Xamarin Forms

I'm building a Xamarin CrossPlatform App!
I wanted to add a floating action button at the bottom right corner of the app page just like this
Here is my XAML code:
<?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="Last_MSPL.Views.HomePage">
<ListView x:Name="Demolist" ItemSelected="OnItemSelected" BackgroundColor="AliceBlue">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem x:Name="OnMore" Clicked="OnMore_Clicked" CommandParameter="{Binding .}"
Text="More" />
<MenuItem x:Name="OnDelete" Clicked="OnDelete_Clicked" CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout>
<StackLayout Padding="15,0">
<Label Text="{Binding employee_name}" FontAttributes="bold" x:Name="en"/>
<Label Text="{Binding employee_age}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
How can I do this using XAML? Help me through this, Thanks!
You can use an ImageButton (Xamarin.Forms v3.4+)
Create your image with a transparent background in your favorite editor and then assign it a location on the Page.
Example using an AbsoluteLayout, just place your "FAB" as the last element so that its Z-order is highest and it will "float" above the rest of the content.
<AbsoluteLayout>
~~~~
<ImageButton Source="editFAB.png"
BackgroundColor="Transparent"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds=".95,.95,80,80"
Clicked="Handle_Clicked" />
</AbsoluteLayout>
Output:
**
If you want a solution thats simple and without downloading libraries or anything try this:
**
In your xaml you can use a normal button with rounded corners. Just make sure both width and height are the same. To have it float use a absolute layout and put the button on the bottom. I pasted mine and its style entry from my app.xml resource dictionary.
(Ive used both the james montenago packages and the suave controls. The first doesn't work on iOS and the latter doesn't show images on Android. This solution works on both iOS and Android.)
XAML:
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<!-- other content goes here -->
<Button x:Name="yourname" Image="baseline_menu_white_24"
Clicked="OnFabMenuClick" IsVisible="True"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
Style="{StaticResource FABPrimary}" />
</AbsoluteLayout>
Resource dictionary entry:
<Color x:Key="DarkButtonBackground">#921813</Color>
<Style x:Key="FABPrimary" TargetType="Button">
<Setter Property="CornerRadius" Value="100"/>
<Setter Property="BackgroundColor" Value="{StaticResource DarkButtonBackground}"/>
<Setter Property="HeightRequest" Value="55"/>
<Setter Property="WidthRequest" Value="55"/>
<Setter Property="HorizontalOptions" Value="CenterAndExpand"/>
<Setter Property="VerticalOptions" Value="CenterAndExpand"/>
<Setter Property="Padding" Value="15"/>
<Setter Property="Margin" Value="0,0,0,15"/>
</Style>
You can ignore the resource dictionary entry if you want and instead put the properties directly in the button declaration in your xaml file.
I have found that on some iOS devices, the buttons do not display correctly if the radius is set to 100. This can be fixed to setting the CornerRadius to half of the width and height, or you can use OnPlatform like this:
<Setter Property="CornerRadius">
<OnPlatform iOS="25" Android="100"/>
</Setter>
(When height and width are both 50.)
It's pretty easy to add a floating button in xamarin forms. Just add a Grid with one row having Height="*" and inside that, add a ScrollView and a Button, both in Grid.Row="0". Inside your ScrollView, put your design form. For button to be round in shape, put some BorderRadius and HeightRequest as well as WidthRequest should be double of that BorderRadius. Also, to show it at bottom right corner, put Margin="0,0,20,22". To show an Icon inside that button, put FontAwesome Icon as ImageSource of the button. FontAwesome Icons can be defined in a separate class (Please let me know if you need details on how to use FontAwesome Icons as well).
That's it, you are done.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollView Grid.Row="0">
</ScrollView>
<Button Grid.Row="0" BorderColor="#2b3c3c" BorderWidth="1" FontAttributes="Bold" BackgroundColor="#1968B3" BorderRadius="35" TextColor="White"
HorizontalOptions="End" VerticalOptions="End" WidthRequest="70" HeightRequest="70" Margin="0,0,20,22" Command="{Binding OpenSearchModalPopupCommand}">
<Button.ImageSource>
<FontImageSource FontFamily="{StaticResource FontAwesomeSolidFontFamily}"
Glyph="{x:Static fonts:Icons.FAFilter}"
Size="20"
Color="White"/>
</Button.ImageSource>
</Button>
</Grid>
the quickest way:
Install this Nuget: https://github.com/jamesmontemagno/FloatingActionButton-for-Xamarin.Android
Position the Floating Action Button (FAB) Like this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="Tawsil.Views.DemoPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:fab="clr-namespace:Refractored.FabControl;assembly=Refractored.FabControl">
<AbsoluteLayout>
<Grid AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All">
<!-- your content here -->
</Grid>
<!-- the FAB -->
<fab:FloatingActionButtonView AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize" AbsoluteLayout.LayoutFlags="PositionProportional" ImageName="add.png" />
</AbsoluteLayout>
</ContentPage>
Don't forget to add the "add.png" icon to your resources
You can use for Android, Floating Action Button (https://developer.android.com/guide/topics/ui/floating-action-button) if you want to use native control, and a custom board for iOS.
Otherwise you can add to your Xamarin.Forms page a RelativeLayout container and specity constraints where you want. Something like this:
<ContentPage.Content>
<RelativeLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout >
<Label Text="YOUR CODE" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />
</StackLayout>
<Button CornerRadius="25" Text="B"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Width, Factor=1, Constant=-60}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height, Factor=1, Constant=-60}" />
</RelativeLayout>
</ContentPage.Content>
You can change Button with any other control and you can correct position just changing the value of "Constant=-60"
Using Floating action button in Xamarin Forms is easier than you might think, All you need is a little bit of AbsoluteLayout and an ImageButton that can respond to your clicks and voila! your FAB is ready
Add a custom ImageButton Control something like below:
public class ImageButton : Image
{
public static readonly BindableProperty CommandProperty =
BindableProperty.Create("Command", typeof(ICommand), typeof(ImageButton), null);
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.Create("CommandParameter", typeof(object), typeof(ImageButton), null);
public event EventHandler ItemTapped = (e, a) => { };
public ImageButton()
{
Initialize();
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
private ICommand TransitionCommand
{
get
{
return new Command(async () =>
{
AnchorX = 0.48;
AnchorY = 0.48;
await this.ScaleTo(0.8, 50, Easing.Linear);
await Task.Delay(100);
await this.ScaleTo(1, 50, Easing.Linear);
Command?.Execute(CommandParameter);
ItemTapped(this, EventArgs.Empty);
});
}
}
public void Initialize()
{
GestureRecognizers.Add(new TapGestureRecognizer
{
Command = TransitionCommand
});
}
}
Once you have that up and running in a layout whose parent-most is an AbsoluteLayout add the ImageButton like below:
<customControls:ImageButton Source="{Binding ImageSource}"
Command="{Binding AddCommand}" AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="1.0,1.0,-1,-1"
Margin="10" />
Where customControls is the namespace where you added your ImageButton custom control.
For better understanding check where I referenced it from which can be found here
Good luck
Revert in case you have any sort of query.
When implementing my Floating Action Button, I noticed that none of the answers here cover the shadow below the button. Here's my (hacky) solution to get a shadow below the FAB:
<Grid>
<Frame
Margin="3,8,-3,-8"
CornerRadius="35"
HasShadow="False"
HeightRequest="70"
VerticalOptions="Start"
WidthRequest="70">
<Frame.Background>
<RadialGradientBrush Center="0.5,0.5" Radius="0.5">
<GradientStop Offset="0" Color="Gray" />
<GradientStop Offset="0.5" Color="Gray" />
<GradientStop Offset="1.0" Color="#01000000" />
</RadialGradientBrush>
</Frame.Background>
</Frame>
<ImageButton
Padding="20"
Command="{Binding <YourCommand>}"
CornerRadius="35"
HeightRequest="70"
Source="<YourImage.png>"
VerticalOptions="Start" />
</Grid>
Notes:
The margin on the frame is the offset wrt to the ImageButton, so it appears below and to the right of the ImageButton.
The last color of the gradient is black, with a 1 value for alpha. Transparent did not have the desired effect on iOS, 01000000 worked nicely.
ImageButton has to be below Frame, because the xaml order determines the draw order.
Put this Grid in another Grid, to make it overlap other content.
This worked for Android and iOS, not for UWP.
I expect this is not a performant solution, because of an additional element to the view, and Xamarin's layout / drawing performance issues. A solution with custom renderers would likely perform better.
To make it nicer still, you can use a Visual State Manager. They left a few bugs in its Xamarin implementation though.

Platform specific CornerRadius on <Frame> Xamarin.Forms

I'm trying to assign different CornerRadius on iOS and Android like following:
<Frame
HasShadow="false"
Padding="10"
BackgroundColor="Red">
<Frame.CornerRadius>
<OnPlatform x:TypeArguments="x:Double">
<On
Platform="iOS">20</On>
<On
Platform="Android">30</On>
</OnPlatform>
</Frame.CornerRadius>
<Label
Text="Hello World" />
</Frame>
But getting a
Cannot assign property "CornerRadius": Property does not exists, or is not assignable, or mismatching type between value and property
I've tried x:TypeArguments="Thickness" and x:TypeArguments="x:Int32". Decompiling the Assembly it appears CornerRadius is of type float. However, there is no Float property in x namespace, I mean x:TypeArguments="x:Float" doesn't exists.
Any ideas what I'm doing wrong or this is a bug?
The CornerRadius type is a Single:
<Frame HasShadow="true" OutlineColor="Red">
<Frame.CornerRadius>
<OnPlatform x:TypeArguments="x:Single">
<On Platform="iOS" Value="20"/>
<On Platform="Android" Value="30"/>
</OnPlatform>
</Frame.CornerRadius>
<Frame.Content>
<Label Text="Welcome to Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />
</Frame.Content>
</Frame>
Well I fell there is a syntax error here do something like this :
<Frame.CornerRadius>
<OnPlatform x:TypeArguments="x:Single">
<OnPlatform.Platforms>
<On Platform="iOS" Value="20" />
<On Platform="Android" Value="30" />
<On Platform="UWP" Value="30" />
</OnPlatform.Platforms>
</OnPlatform>
</Frame.CornerRadius>
Try this and in case it doesn't work kindly revert.

How to change icon color in Xamarin.Forms xaml page?

Currently, I am developing a Xamarin.Forms PCL application for Android and iOS. In one of my pages I define a ListView. The template for the ListView.ItemTemplate displays an icon using <Image Source="some_Icon.png" />. The icon displays as expected (black) but I have not found a way to set the color.
I would like to colorize this icon based on logic in my ViewModel.
I have searched for answers both through the Documentation and StackOverlflow to no avail.
Is there a better way to display and style icons from a Xamarin.Forms PCL project?
Does Xamarin.Forms require a set of resource/image files for every possible color I might use?
I solved my problem with Iconize for Xamarin.Forms. I implemented my solution based off the Iconize sample code below.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:iconize="clr-namespace:FormsPlugin.Iconize;assembly=FormsPlugin.Iconize"
x:Class="Iconize.FormsSample.Page1"
Title="{Binding FontFamily}">
<ContentPage.ToolbarItems>
<iconize:IconToolbarItem Command="{Binding ModalTestCommand}" Icon="fa-500px" />
<iconize:IconToolbarItem Command="{Binding VisibleTestCommand}" Icon="fa-500px" IconColor="Red" />
<iconize:IconToolbarItem Command="{Binding VisibleTestCommand}" Icon="fa-500px" IsVisible="{Binding VisibleTest}" />
</ContentPage.ToolbarItems>
<ListView CachingStrategy="RecycleElement" ItemsSource="{Binding Characters}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<iconize:IconImage HeightRequest="20" Icon="{Binding Key}" IconColor="Blue" WidthRequest="20" />
<iconize:IconImage HeightRequest="20" Icon="{Binding Key}" BackgroundColor="Blue" IconColor="Yellow" WidthRequest="20" IconSize="10" />
<iconize:IconButton FontSize="20" Text="{Binding Key}" TextColor="Red" WidthRequest="48" />
<iconize:IconLabel FontSize="20" Text="{Binding Key}" TextColor="Green" VerticalTextAlignment="Center" />
<Label Text="{Binding Key}" VerticalTextAlignment="Center" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
In my case, I simply had to replace my original <Image .../> element and replace it with
<iconize:IconImage HeightRequest="20" Icon="fa-circle" IconColor="{Binding CircleColor}" WidthRequest="20" />.
In my ViewModel, I added the CircleColor property to set the icon color as needed based on my logic.