Xamarin.Forms ImageButton Display Issue - xamarin

I am trying to use an ImageButton in a StackLayout and attempting to set the text of the button to be set below the image. However, the text is always displayed on the right side of the image instead of below. here is the code:
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout x:Class="MyApp.Portable.Controls.MyNavigationControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
xmlns:forms="clr-namespace:Xamarin.Forms;assembly=Xamarin.Libraries.PCL"
x:Name="MyNavControl"
BackgroundColor="White"
HorizontalOptions="FillAndExpand"
MinimumHeightRequest="75"
Orientation="Horizontal">
<StackLayout.Resources>
<ResourceDictionary>
<Style x:Key="NavButtonStyle" TargetType="Button">
<Setter Property="BackgroundColor" Value="White" />
<Setter Property="TextColor" Value="Gray" />
<Setter Property="FontSize" Value="7" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<forms:ImageButton x:Name="GpsButton"
Clicked="GpsBUttonClicked"
Image="GPS_Icon_Light_Gray_sm.png"
MinimumHeightRequest="75"
Orientation="ImageOnBottom"
Style="{StaticResource NavButtonStyle}"
Text="GPS"
VerticalOptions="Start" />
<StackLayout>

In case you haven't found it yet, here is the answer to your question. The problem is a matter of using the incorrect property to set the Image. The ImageButton.Image property will display the image however it will not adhere to any other set properties such as ImageButton.Orientation. To solve your issue you must set the ImageButton.Source property instead.
More info can be found here: https://github.com/XLabs/Xamarin-Forms-Labs/issues/235

Related

Xamarin: How to Add a Background Image to All Pages with an AspectFill property

Total newbie Xamarin user.
I'm trying to add a background image to all the pages in the mobile app.
This was a great resource: Xamarin.Forms How to add Backgroud Image on all pages in App
However, I'd like to adjust the Aspect property of the image to AspectFill, so it's not so scrunched up. This is where I'm having trouble.
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.App">
...
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True" >
<Setter Property="BackgroundImageSource" Value="background_image.png" />
</Style>
...
This sets the background image. How do I adjust the Aspect property for all pages? I've tried nesting an <Image Aspect="AspectFill" /> tag within the Setter property tag, but VS gives a warning that the "property 'Value' is set more than once". Could someone help me out? I'm sure I'm making some dumb error or I've misunderstood something about Xamarin.
Thanks.
Yes, we can use the following method to set the BackgroundImageSource for all ContentPage in your app:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True" >
<Setter Property="BackgroundImageSource" Value="background_image.png" />
</Style>
</ResourceDictionary>
</Application.Resources>
But we couldn't set the AspectFill property for it while Aspect is specifically a property of the Image control as jason said.
Of course,if you need a solution that allows you to change the AspectRatio and adjust the image you can use this:
<?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="Pages.PhotoPage">
<Grid >
<Image Source="background.png" Aspect="AspectFit" />
<!-- Place here the rest of the layout for the page. -->
</Grid >
</ContentPage>
Or use the solution j-petty said:
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Image AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" Source="sample.jpg" Aspect="AspectFill"/>
<StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="1,1,1,1">
<!--Content-->
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" >
<Label x:Name="KategoriePicker" Text="Was möchtest du essen?" BackgroundColor="White" />
<Label x:Name="OrtTextBox" Text="Dein Lieferort" BackgroundColor="White" />
</StackLayout>
</StackLayout>
</AbsoluteLayout>

Is there a way I can add resources to a page in the C# backend?

I have pages that look like this:
<?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:local="clr-namespace:Japanese;assembly=Japanese" xmlns:template="clr-namespace:Japanese.Templates" xmlns:t="clr-namespace:Japanese.Views.HelpTab.Xaml" x:Class="Japanese.Views.HelpTab.AssignMode" Title="Assign Mode Help" BackgroundColor="{DynamicResource PageBackgroundColor}">
<ContentPage.Content>
<ScrollView>
<StackLayout Spacing="0">
<StackLayout.Resources>
<Style TargetType="Frame" CanCascade="true">
<Setter Property="Style" Value="{StaticResource FrameBorder}" />
</Style>
<Style TargetType="Label" CanCascade="true">
<Setter Property="TextColor" Value="{DynamicResource HelpTextColor}" />
<Setter Property="Style" Value="{StaticResource HD}" />
</Style>
<Style TargetType="Grid" CanCascade="true">
<Setter Property="Style" Value="{StaticResource HG}" />
</Style>
</StackLayout.Resources>
There are about twenty pages in the application that all have the same set of Resources added but not every page.
Is there a way that I can add the resources in the C# backend of my own page and then usesenter code here that for those twenty pages so that all I would need to do is something like this:
<?xml version="1.0" encoding="UTF-8"?>
<MyContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Japanese;assembly=Japanese" xmlns:template="clr-namespace:Japanese.Templates" xmlns:t="clr-namespace:Japanese.Views.HelpTab.Xaml" x:Class="Japanese.Views.HelpTab.AssignMode" Title="Assign Mode Help" BackgroundColor="{DynamicResource PageBackgroundColor}">
<ContentPage.Content>
<ScrollView>
<StackLayout Spacing="0">
Alternatively is there some way I could combine all those resources into just one and add that rather than adding the three individual styles?
Sure, there are a couple of things you can do in this area, but I think it will already help you a lot to know there are implicit and explicit styles.
Start by going to your App.xaml and add your styles there. You should see the <Application.Resources> node already there. You can add the <ResourceDictionary> in there and now define any resources or styles as you wish. Those will be available throughout the whole app.
For instance, in your case, like this:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="Frame" CanCascade="true">
<Setter Property="Style" Value="{StaticResource FrameBorder}" />
</Style>
<Style TargetType="Label" CanCascade="true">
<Setter Property="TextColor" Value="{DynamicResource HelpTextColor}" />
<Setter Property="Style" Value="{StaticResource HD}" />
</Style>
<Style TargetType="Grid" CanCascade="true">
<Setter Property="Style" Value="{StaticResource HG}" />
</Style>
</ResourceDictionary>
</Application.Resources>
Because you are specifying the TargetType and not an x:Key, this is an implicit style. It will apply to all elements of that target type. There is two things you can do now; or create an inheritance of the control and apply the style only to that inheritance, or create an explicit style. You then add the x:Key="MyStyle" attribute to a style and add the Style="{StaticResource MyStyle}" to each element you want to apply the style to. More on styles can be read on the Microsoft Docs.
You can define resources in App.xaml and use in an entire project using
Application.Current.Resources["AppColor"];
If you want to use in xaml page the use like
<Label TextColor={Binding StaticResource AppColor}/>

Avoid to refer styles in all pages - Xamarin.Forms

I'm working on a Xamarin Forms app for mobile cross platform.
I found how to apply styles to my pages and controls in this way:
Styles/HeaderStyle.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.HeaderStyle">
<Style x:Key="Header" TargetType="StackLayout">
<Setter Property="Orientation" Value="Horizontal"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="BackgroundColor" Value="Green"/>
</Style>
</ResourceDictionary>
Views/Page.xaml
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.HomePage"
xmlns:local="clr-namespace:App;"
NavigationPage.HasNavigationBar="false">
<ContentPage.Resources>
<ResourceDictionary MergedWith="local:HeaderStyle">
</ResourceDictionary>
</ContentPage.Resources>
<!-- Some other page content -->
</ContentPage>
I have some doubt about this implementation:
- I can't figure out how to add multiple style files
- I've to add the style file references to all the pages
I've tried to add the reference in App.xaml in some way like this
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="theme:Resources1"/>
<ResourceDictionary Source="theme:Resources2"/>
</ResourceDictionary.MergedDictionaries>
But without success.
If you have styles that you use everywhere, you can put them in a global style.
In your App.xaml you can define a ResourceDictionary just like you have now. For example:
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.App">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderColor" Value="Lime" />
<Setter Property="BorderRadius" Value="5" />
<Setter Property="BorderWidth" Value="5" />
<Setter Property="WidthRequest" Value="200" />
<Setter Property="TextColor" Value="Teal" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Then in your page you should be able to refer to them without having to declare the merging of the dictionary, like so:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.ApplicationStylesPage" Title="Application" Icon="xaml.png">
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Button Text="These buttons" Style="{StaticResource buttonStyle}" />
<Button Text="are demonstrating" Style="{StaticResource buttonStyle}" />
<Button Text="application style overrides" Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
If you were to override the style, you could do so by declaring a style in that page, styles lower in the hierarchy take precendence over the styles higher up.
You could also choose not to add the x:Key attribute on a style to make it implicit. That way you do not have to declare the Style property on a control.

how to define/override Style for ContentView when it is child of ContentPage

I have contentview as below
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:convertors="clr-namespace:myApp.Convertors;assembly=myApp"
x:Class="myApp.cwPart">
<ContentView.Content>
<StackLayout Orientation="Horizontal"
BackgroundColor="White">
<RelativeLayout Style="{StaticResource myStyle}"
HorizontalOptions="Start"
VerticalOptions="Center">
I am referencing this ContentView inside multiple ContentPages as example one below. Every ContentPage should set different BackgroundColor, Height and Width. That's why I thought that style should be defined in the ContentPage but it is throwing error that it is not recognized. How can I achieve this?
PS, interesting thing I am using Gorilla player to achieve such changes and Gorilla player doesn't return any error :)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:convertors="clr-namespace:myApp.Convertors;assembly=myApp"
xmlns:c="clr-namespace:myApp;assembly=myApp"
x:Class="myApp.AppLogsPage"
Title="{Binding AppName}"
x:Name="AppLogsPage">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="myStyle" TargetType="RelativeLayout">
<Setter Property="HeightRequest" Value="148"/>
<Setter Property="WidthRequest" Value="80"/>
<Setter Property="BackgroundColor" Value="White"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout x:Name="MainHolder">
<c:cwPart />
...
If I define ContentView Resources as below, it works fine but I am not able to override the Style defined inside ContentView
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:convertors="clr-namespace:myApp.Convertors;assembly=myApp"
x:Class="myApp.cwPart">
<ContentView.Resources>
<ResourceDictionary>
<Style x:Key="myStyle" TargetType="RelativeLayout">
<Setter Property="HeightRequest" Value="148"/>
<Setter Property="WidthRequest" Value="80"/>
<Setter Property="BackgroundColor" Value="White"/>
</Style>
</ResourceDictionary>
</ContentView.Resources>
<ContentView.Content>
<StackLayout Orientation="Horizontal" BackgroundColor="White">
<RelativeLayout Style="{StaticResource myStyle}"
HorizontalOptions="Start" VerticalOptions="Center" >
There are many issues i would change in your approach but let's keep it simple. First of all i would use contentview with control template as;
in App.xaml;
<ControlTemplate x:Key="MyControlTemplate">
<StackLayout Orientation="Horizontal" BackgroundColor="White">
<RelativeLayout HorizontalOptions="Start" VerticalOptions="Center" />
</StackLayout>
</ControlTemplate>
then in your page.xaml
<ContentView ControlTemplate={StaticResource MyControlTemplate}/>
if you want to set individual styles for every page then you can create a control template for each of them.
To create a WPF like user control;
in App.xaml;
<ControlTemplate x:Key="MyControlTemplate">
<StackLayout Orientation="Horizontal" BackgroundColor="White">
<RelativeLayout HorizontalOptions="Start" VerticalOptions="Center" />
</StackLayout>
</ControlTemplate>
in the same project
public class CustomView: ContentView
{
public CustomView()
{
ControlTemplate = (ControlTemplate)Application.Current.Resources.FirstOrDefault(x => x.Key == "MyControlTemplate").Value;
}
}
then you can use CustomView control/view in any xaml page. Don't forget to add xaml namespace of the CustomView in consuming xaml page.

ListView padding before and after items

My ListViews all add a huge amount of padding before and after their children.
For example I have the following ListView in my master
<?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:viewModel="clr-namespace:ViewModel;assembly=App"
x:Class="Pages.Master"
Title="Menu">
<ContentPage.BindingContext>
<viewModel:MasterViewModel />
</ContentPage.BindingContext>
<ListView ItemsSource="{Binding Pages}"
ItemSelected="ListView_OnItemSelected"
BackgroundColor="Red">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="S" BackgroundColor="White" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
And it renders the following:
And as soon as you scroll just a little it'll reveal the first element (i.e. the top red space is equal to the height)
Similarly you can keep scrolling until the last item completely disappears (i.e. the bottom red space is equal to the height)
I don't change the properties/styling of ANY of the views in code - it's all done in the XAML, so why is there such a huge amount of space before and after?
It appears to be a problem with the rendering of ListView.Header and ListView.Footer
I added the following to my list view XAML and it removed the giant padding:
<ListView.Header>
<StackLayout HeightRequest="0" />
</ListView.Header>
<!-- ItemTemplate -->
<ListView.Footer>
<StackLayout HeightRequest="0" />
</ListView.Footer>
As this problem was affecting all of my list views, I chose to instead add it as a globally applied style in my App.xaml:
<Style TargetType="ListView">
<Setter Property="Header">
<Setter.Value>
<StackLayout HeightRequest="0" />
</Setter.Value>
</Setter>
<Setter Property="Footer">
<Setter.Value>
<StackLayout HeightRequest="0" />
</Setter.Value>
</Setter>
</Style>

Resources