Xamarin.Forms (XAML): scaling to smaller screens - android

I have been developing an application using Xamarin Forms and am having problems with smaller screen sizes (480x640 and 480x800 for example). Basically, the content of the form is being clipped...
Note the buttons at the bottom have been clipped.
Within the XAML I am not specifying any sizes so I expect the forms to adapt to the available size...
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Class="MyCompany.Views.MyPage" x:Name="MyPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:views="clr-namespace:MyCompany.Views" Padding="15" Title="{Binding Path=Title}">
<StackLayout>
<StackLayout VerticalOptions="Start">
<Label HorizontalTextAlignment="Center" Text="Type barcode manually if required" />
<Entry Text="{Binding Path=BarcodeContent}" />
<Button Command="{Binding Path=OkCommand}" HorizontalOptions="Center" Text="Ok" />
</StackLayout>
<ListView ItemsSource="{Binding Path=History}" VerticalOptions="Fill">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Path=BarcodeContent}">
<TextCell.ContextActions>
<MenuItem Command="{Binding Path=BindingContext.EnquiryCommand, Source={x:Reference MyPage}}" CommandParameter="{Binding}" Text="Enquiry" />
<MenuItem Command="{Binding Path=BindingContext.RaiseCommand, Source={x:Reference MyPage}}" CommandParameter="{Binding}" Text="Raise" />
</TextCell.ContextActions>
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Grid VerticalOptions="End">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Command="{Binding Path=CancelCommand}" Text="Cancel" />
<Button Grid.Column="3" Command="{Binding Path=ContinueCommand}" Text="Complete" />
</Grid>
</StackLayout>
</ContentPage>
When displayed on a 1080 x 1920 pixel display, all is well.
What am I missing here?
EDIT:
If I replace the outer StackView with a Grid, everything fits...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0">
</StackLayout>
<ListView Grid.Row="1" ...>
</ListView>
<Grid Grid.Row="2">
</Grid>
</Grid>
So, I have a work around but still do not understand why the original StackView version does not work (is there a preferred default height to the ListView control for example?).

While I would have to delve down in to the code to find the exact reason, the most likely suspect is the ListView. The StackLayout doesn't just fit the screen, it expands to contain everything that is inside of it.
The ListView, most likely is bigger than anticipated, due to the VerticalOptions="Fill" and hence is taking all that space you are seeing. If you change the background color on your ListView, you will see what area it is taking. But you can change the background color on all containers on the screen, and its normally the best way to see whats taking space.
A Grid on the other hand, will just fill the exact space on the screen, and its rows are split with what space is available inside.
To summarize, a StackLayout expands beyond the screen to fit what is contained inside it. A Grid will fill out to the size of its parent, e.g. the screen, by default, then you split the space inside of it.

I have changed your XAML. Can you check this, might be helpful for you
<StackLayoutSpacing="2">
<StackLayout>
<Label HorizontalTextAlignment="Center" Text="Type barcode manually if required" />
<Entry Text="{Binding Path=BarcodeContent}" />
<Button Command="{Binding Path=OkCommand}" HorizontalOptions="Center" Text="Ok" />
</StackLayout>
<ListView ItemsSource="{Binding Path=History}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Path=BarcodeContent}">
<TextCell.ContextActions>
<MenuItem Command="{Binding Path=BindingContext.EnquiryCommand, Source={x:Reference MyPage}}" CommandParameter="{Binding}" Text="Enquiry" />
<MenuItem Command="{Binding Path=BindingContext.RaiseCommand, Source={x:Reference MyPage}}" CommandParameter="{Binding}" Text="Raise" />
</TextCell.ContextActions>
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout HeightRequest="55" Padding="10" Orientation="Horizontal" BackgroundColor="#E3714D" >
<Button Command="{Binding Path=CancelCommand}" Text="Cancel" />
<Button Command="{Binding Path=ContinueCommand}" Text="Complete" />
</StackLayout>
</StackLayout>
You can also use the grid inside/instead of StackLayout containing the button.

Related

.Net MAUI: Different result for CollectionView/DataTemplate between Android and iOS

I wrote a simple CollectionView (.Net MAUI) with a DataTemplate and get completely different results when I deploy the code to either a Android device or a iOS device.
It would be really awesome if someone has a hint - this project drives me crazy since 4 months :D
I used the same code in Xamarin before without any issues.
EDIT:
I added the WidthRequest (and a margin) and now the style is as expected - thanks so far. (I also checked the text colors which are fine and I changed the TextColor of two lables to red - just for testing)
But I still have another issue. When the iOS App is opened, the part on the right hand side does not show up and it seems that the app is hung up. If I try to scroll, then I get a completlely random list of my items (some are missing) and everything is stuck.
<RefreshView x:DataType="local:ItemsViewModel" Command="{Binding LoadItemsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<CollectionView x:Name="ItemsListView" ItemsSource="{Binding Items}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10" x:DataType="model:Cryptocurrency">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Image Source="{Binding image}" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" HeightRequest="50" WidthRequest="50" Margin="0,0,10,0" />
<Label Text="{Binding name}" Grid.Row="0" Grid.Column="1"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="Price" Grid.Row="0" Grid.Column="2"
LineBreakMode="NoWrap" HorizontalTextAlignment="End" Padding="0,0,20,0"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="x to ATH" Grid.Row="0" Grid.Column="3"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="{Binding market_cap_rank}" Grid.Row="1" Grid.Column="1"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
<Label Text="{Binding current_price, StringFormat='{}{0:C}'}" Grid.Row="1" Grid.Column="2"
LineBreakMode="NoWrap" HorizontalTextAlignment="End" Padding="0,0,20,0"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
<Label Text="{Binding RatioToATH}" Grid.Row="1" Grid.Column="3"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
<Grid.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemsViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
EDIT2:
It also works flawlessly on macOS (MacCatalyst)
You could set the constraint of Image(give it a width), please refer to the following code.
<Image Source="{Binding image}" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" HeightRequest="50" WidthRequest="150" />
Yes! this is how MAUI work they will call out the native controls instead of control that is written in the middle layer like Flutter
They provide you OnPlatform so you can easily adjust the UI better
IsVisible={x:OnPlatform WinUI=true, Android=false, iOS=false, Tizen=false, MacCatalyst=false}

Xamarin Forms CarouselView too long

Elongated Carousel View
I have used Xamarin's native CarouselView as below and it is retrieving data as it is supposed to.
The problem is that the individual columns are too long (elongated more than the content). I want an effect similar to that of shopping sites where the individual column height fits the content as with ASP.NET DIV Card. I have tried to use two carousels to see if it is a bug but both carousels expand beyond the height needed.
I have tried using StackLayout the problem still persists. Is there a simple template that you can direct me to or some correction that is needed?
//James
<?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:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="ApplicationName.Views.HomePage">
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="tlbarLogin" Text="Sign Up/Login" Clicked="Launch_Login"/>
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="Accent">#96d1ff</Color>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout BackgroundColor="#2C5C2C" VerticalOptions="FillAndExpand" HorizontalOptions="Fill">
<SearchBar BackgroundColor="White" Placeholder="Search items..." PlaceholderColor="LightGray"
CancelButtonColor="black"
TextColor="Black"
FontSize="Medium"
/>
</StackLayout>
<ScrollView Grid.Row="1">
<!--<StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10">-->
<Grid Margin="0, 5, 0, 0">
<Grid.RowDefinitions>
<!--One RowDefinition in * si useless by the way -->
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackLayout>
<CarouselView x:Name="TheCarousel" PeekAreaInsets="50" Loop="False" Grid.ColumnSpan="5">
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="10"
VerticalOptions="Start" >
<StackLayout >
<Image Source="{Binding strImagePath}" Aspect="AspectFill"/>
<Label Text="{Binding strLocalisedString}" FontSize="20"/>
</StackLayout>
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<CarouselView x:Name="TheCarousel2" PeekAreaInsets="50" Loop="False" Grid.ColumnSpan="5">
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="10"
HeightRequest="50"
VerticalOptions="Start" >
<StackLayout >
<Image Source="{Binding strImagePath}" Aspect="AspectFill"/>
<Label Text="{Binding strLocalisedString}" FontSize="20"/>
</StackLayout>
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
<!--</StackLayout>-->
</Grid>
</ScrollView>
</Grid>
</ContentPage>
Adding Height to Carousel as suggested by Jason worked
I simply added the HeightRequest value to the CarouselVeiw elements and they adjusted themselves to the set height of "250".

Image overflow in ListView Xamarin.Forms (Android)

have a ListView in which for each element of the List you have 3 buttons for 3 different options, when you enter the screen there are no overflow problems in the images of the ImageButton, but when you do the first scroll the sources start to overflow as shown in the following image
The images lose the center and are misaligned as you scroll up or down, this problem does not occur in iOS, only occurs in Android (version 6,7,8 and 9), apparently it is a problem like Android render the images
I tried, changing the ImageButton control to Button and the problem persists, also trying to assign the "Aspect" property to the ImageButton, but I'm not getting successful results, any help how to fix this? then my code XAML
<ListView
ItemsSource="{Binding ListaRecintos}"
SelectionMode="None"
IsRefreshing="{Binding IsRefreshing, Mode=TwoWay}"
RowHeight="80"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
Margin="0,4,0,0"
Orientation="Vertical">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="3.9*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label
Text="{Binding Code}"
HorizontalOptions="Start"
FontSize="Small"
WidthRequest="40"
HeightRequest="30"
FontAttributes="Bold"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand"
Grid.Column="0">
</Label>
<StackLayout Orientation="Vertical"
Grid.Column="1">
<Label
Text="{Binding Name}"
HorizontalOptions="Start"
FontSize="Small"
HeightRequest="32"
MaxLines="2"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="Center"
VerticalTextAlignment="Center">
</Label>
</StackLayout>
</Grid>
<!--STACK BUTTON-->
<StackLayout
Orientation="Horizontal"
HorizontalOptions="EndAndExpand"
Margin="0,1,1,0">
<!--BUTTON 1-->
<ImageButton
Source="ic_check_wt"
Aspect="AspectFit"
CornerRadius="0"
BackgroundColor="{StaticResource das.color.estado_success}"
HorizontalOptions="End"
VerticalOptions="Center"
HeightRequest="35"
WidthRequest="50"
CommandParameter="2"
Command="{Binding ControlAuditoriaCommand}"
IsEnabled="{Binding EnabledButton}"/>
<!--BUTTON 2-->
<ImageButton
Source="ic_hammer"
BackgroundColor="{StaticResource das.color.estado_primary}"
HorizontalOptions="End"
CornerRadius="0"
Aspect="AspectFit"
VerticalOptions="Center"
HeightRequest="35"
WidthRequest="50"
CommandParameter="1"
Command="{Binding ControlAuditoriaCommand}"
IsEnabled="{Binding EnabledButton}"/>
<!--BUTTON 3-->
<ImageButton
Source="ic_arrow_up"
BackgroundColor="{StaticResource das.color.estado_success}"
HorizontalOptions="End"
CornerRadius="0"
Aspect="AspectFit"
VerticalOptions="Center"
HeightRequest="35"
WidthRequest="50"
CommandParameter="3"
Command="{Binding ControlAuditoriaCommand}"
IsEnabled="{Binding EnabledButton}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
How can I avoid this behavior? Any help for me?
I suggest you use (Frame + image ) instead of ImageButton , and add tapgesture on it .

Element not expanding in Xamarin.Forms

Using StartAndExpand or EndAndExpand does not seem to actually expand the elements inside StackLayout. Even though there is more space available as seen in the blue area. Only FillAndExpand works.
Here is the 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"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:local="clr-namespace:App6"
x:Class="App6.MainPage"
ios:Page.UseSafeArea="True">
<StackLayout BackgroundColor="Blue"
HeightRequest="100"
Orientation="Horizontal"
Spacing="0"
VerticalOptions="Start">
<Label BackgroundColor="Red"
HorizontalOptions="Start"
Text="Hi" />
<StackLayout BackgroundColor="Salmon"
HorizontalOptions="EndAndExpand"
Orientation="Vertical">
<BoxView BackgroundColor="Red"
HeightRequest="30"
HorizontalOptions="End"
VerticalOptions="Center"
WidthRequest="30" />
</StackLayout>
</StackLayout>
</ContentPage>
And here is what I get:
Top result is when using FillAndExpand for the child StackLayout, followed by EndAndExpand which does not expand, and lastly StartAndExpand, which also does not expand.
Isn't expand supposed to expand the element if the parent element has more space? If yes, why then StartAndExpand and EndAndExpand does not work?
Note: This is tested on Android only with Xamarin.Forms version 3.4.0.1008975.
Referring to #AndroDevil comment, the space is actually distributed between StackLayout's child elements, but they cannot fill it, unless their layout option contains Fill. It works more or less like FlexLayout's space between option.
I just added another element to the StackLayout, and it is clearer now what is going on.
Here is the 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"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:local="clr-namespace:App6"
x:Class="App6.MainPage"
ios:Page.UseSafeArea="True">
<StackLayout BackgroundColor="Blue"
HeightRequest="100"
Orientation="Horizontal"
Spacing="0"
VerticalOptions="Start">
<Label BackgroundColor="Red"
HorizontalOptions="Start"
Text="Hi" />
<Label BackgroundColor="Red"
HorizontalOptions="EndAndExpand"
Text="Bye" />
<StackLayout BackgroundColor="Salmon"
HorizontalOptions="EndAndExpand"
Orientation="Vertical">
<BoxView BackgroundColor="Red"
HeightRequest="30"
HorizontalOptions="End"
VerticalOptions="Center"
WidthRequest="30" />
</StackLayout>
</StackLayout>
</ContentPage>
And here what I get:
So Expand mean the following:
StartAndExpand: Give me more space, but put me to the left.
CenterAndExpand: Give me more space, but put me in the center.
EndAndExpand: Give me more space, but put me to the right.
FillAndExpand: Give me more space, I am gonna fill it.
Cause: When you add labels in stackLayout ,stackLayout will not make the subviews fit the size.
Solution:
Put the labels in a Grid. Refer the following code.
For example: If you want to set the label "Hi" as half of width of screen
<Grid BackgroundColor="Blue" >
<Grid.RowDefinitions>
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label HeightRequest="100" Grid.Row="0" Grid.Column="0" Text="Hi" BackgroundColor="Red" />
<BoxView Grid.Row="0" Grid.Column="1" BackgroundColor="Red"
HeightRequest="30"
HorizontalOptions="End"
VerticalOptions="Center"
WidthRequest="30"/>
</Grid>

xamarin cross platform form for buttons with image and text layout

I am looking to create a xamarin cross platform dashboard page with some buttons. Each button have an icon image and a text. I tried two approaches 1. with using inbuilt property of Icon of Button control and another with separate StackLayout
But my output needs some optimization on xaml
The xaml i tried is like this
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="150" ></RowDefinition>
<RowDefinition Height="150"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" BackgroundColor="#3094d2" >
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Image Source="#drawable/announcement.png" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button Text="Announcement" TextColor="White" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
</StackLayout>
<Button Text="News & Events" Grid.Row="0" Grid.Column="1" BackgroundColor="#287cbe" Image="#drawable/announcement.png" TextColor="White" Clicked="Button_NewsHome_Clicked" />
<Button Text="Messages" Grid.Row="1" Grid.Column="0" BackgroundColor="#5153a9" Image="#drawable/announcement.png" TextColor="White" Clicked="Button_SMSHome_Clicked" />
<Button Text="SMS Alers" Grid.Row="1" Grid.Column="1" Image="#drawable/announcement.png" BackgroundColor="#a434a6" TextColor="White" Clicked="Button_SMSHome_Clicked" />
</Grid>
What adjustments i have to do on Vertical and Horizontal align to make my ouput looks like that on the left side
You can use XLabs Extended Button to get desired output

Categories

Resources