Xamarin Forms group controls without modifying layout - xamarin.forms

I've got following view:
<ContentPage.Content>
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<StackLayout VerticalOptions="CenterAndExpand" Margin="20, 0, 20, 0">
<StackLayout>
<Label Text="Login" HorizontalOptions="CenterAndExpand" />
<Entry Text="{Binding Login, Mode=OneWayToSource}"></Entry>
</StackLayout>
<StackLayout>
<Label Text="Hasło" HorizontalOptions="CenterAndExpand" />
<Entry IsPassword="True" Text="{Binding Password, Mode=TwoWay}"></Entry>
</StackLayout>
<Button Text="Zaloguj się" Command="{Binding SignInCommand}"></Button>
</StackLayout>
</StackLayout>
<BoxView AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" BackgroundColor="Gray" Opacity="0.5" InputTransparent="false" IsVisible="{Binding IsBusy}" />
<ActivityIndicator IsRunning="{Binding IsBusy}" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />
</AbsoluteLayout>
</ContentPage.Content>
I want to move BoxView and ActivityIndicator to external control to make reusable component. The problem is that to achieve this I need to "group" these controls to obtain one child element.
The question is if is there any element I can use to group my controls, but which will not affect the way how controls are displayed? Alternatevlly which element I can use and how to still have effect of overlay over whole page and loading indicator?
I was trying to use AbsoluteLayout, StackLayout etc. but I couldn't position it to persist initial effect (overlay on whole page and loading indicator in the center with opacity = 1).

You can use DependencyService and reuse it in any page.
Check this tutorial.
There is also a working sample.

Related

Remove CarouselView WhiteSpace

I'm trying to implement a CarouselView to display a set of images on my app. Apparently, I can't remove the Whitespace at the Bottom of the CarouselView no matter what combinations I tried.
I've placed BackgroundColor property for CarouselView [Red], Grid[Green] (inside DataTemplate), and IndicatorView [Blue] to see which of them is consuming the rest of the screen despite the lack of StackLayout and it seems that either CarouselView or Grid is causing the unwanted behaviour.
Here's my XAML Code with roughly nothing on the ViewModel but a Mock Database for the Image Collection:
<ContentPage.Content>
<Grid ColumnDefinitions="*"
RowDefinitions="Auto,Auto,Auto,1*">
<Label Grid.Row="0" Grid.Column="0"
Text="CarouselView Test"
TextColor="Black"
FontAttributes="Bold"
FontSize="20"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
Padding="10" />
<CarouselView Grid.Row="1" Grid.Column="0" BackgroundColor="Red" HeightRequest="{Binding ScreenWidth}"
x:Name="TheCarousel"
ItemsSource="{Binding ImageSourceCollection}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="Auto" ColumnDefinitions="Auto" BackgroundColor="Green" HorizontalOptions="Center" VerticalOptions="Center">
<Image Grid.Row="0" Grid.Column="0" Source="{Binding .}" />
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView Grid.Row="2" Grid.Column="0" BackgroundColor="Blue"
x:Name="indicatorView"
IndicatorColor="LightGray"
IndicatorSize="10"
SelectedIndicatorColor="Black" />
</Grid>
</ContentPage.Content>
And here's a screenshot of my current build with the CarouselView/Grid consuming most of the Screen Space:
CarouselView has some weird behaviors on size calculating,in your scenario the only way is get the height it(template) needs in code(viewmodel), and bind it to the HeightRequest on CarouselView .
Xaml
<CarouselView HeightRequest="{Binding xxx}"
View model
public double xxx {
get
{
// calculate the height according to the width by ratio
return height;
}
}
I think you need to set Space between rows and columns to Zero if you want to make your indicatorView stick to your CarouselView
So what actually worked for me.
I set Grid Row Definition to ex.(300) and then Carousel Height Request to 350.
I'm setting Image Width based on Screen Width, but I tried it Manually ex (400) and still worked, don't get confused.
<Grid RowDefinitions="300">
<CarouselView x:Name="carouselView"
Grid.Row="0"
ItemsSource="{Binding HomeCarousel}">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="False"
CornerRadius="0"
Margin="0"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
HeightRequest="350">
<SwipeView>
<Image Source="{Binding ImageSource}"
Aspect="AspectFill"
WidthRequest="{DynamicResource FullScreenWidth}"
HorizontalOptions="Center" />
</SwipeView>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>

How to make a semi-transparent background image on xamarin

I have to opacify (make semi-transparent) the background image with a colored veil, I tried adding a frame but I don't get the desired effect`
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewmodels="clr-namespace:GET_SOUND_V2.ViewModels" x:DataType="viewmodels:LoginViewModel"
mc:Ignorable="d"
x:Class="GET_SOUND_V2.Views.LoginPage"
BackgroundImage="maco.jpg">
<ContentPage.Content>
<Frame BorderColor="Transparent" Opacity="0.7">
<Frame.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<GradientStop Color="#1d57a8"
Offset="0.1"/>
<GradientStop Color="#1d57a8"
Offset="1.0"/>
</LinearGradientBrush>
</Frame.Background>
<StackLayout Orientation="Vertical" Padding="30" Spacing="40">
<BoxView HeightRequest="30"/>
<StackLayout Orientation="Vertical">
<Entry x:Name="txtUserName" Text="{Binding UserName}" HorizontalTextAlignment="Center" Placeholder="UserName"
PlaceholderColor="White" HeightRequest="40"
Keyboard="Email"
TextColor="White"
Focused="BiometricCredentials" />
<Entry x:Name="txtPassword" Text="{Binding Password}" HorizontalTextAlignment="Center" Placeholder="Password"
PlaceholderColor="White" HeightRequest="40"
IsPassword="True"
TextColor="White"/>
</StackLayout>
<Button Command="{Binding SubmitCommand}" Text="Accedi" TextColor="White" CornerRadius="50"
FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand"
Margin="0,0,0,150" BackgroundColor="#EF7F1A" />
</StackLayout>
</Frame>
</ContentPage.Content>
</ContentPage>
I would like the elements, however, not to be affected by the opacity value (still be fully opaque), any advice on how I could do?
One approach is to "overlay" two elements over each other, using a single-cell Grid.
The "underneath" item is the image (with opacity applied).
The "top" item is the rest of your layout.
.
<Grid>
<Frame ...>
...
</Frame>
<StackLayout ...>
...
</StackLayout>
</Grid>
Notice that StackLayout is no longer inside Frame. Because no Grid.Row or Grid.Column is specified on these two elements, they both are at Row=0, Column=0. Hence, overlaid one on top of the other.
May need to add properties to <Grid> element, to get desired size, etc. But start with what I show, see what happens.

Xamarin Forms CarouselView and ScrollView already scrolled without visited

I have a CarouselView with inside a ScrollView .
I've seen it plastered across documentation that it's not advisable to nest a scrollview inside any other scrollable layout, but what else can I do when I need to be able to scroll between items and each item must have scrollable content also.
Now my problem is with iOS (with all version after 10+) and Android (will all version after 6+). Let's assume we have 10 items and during the first display I make a vertical scroll in the middle of the content. When I get to the fifth view it is not displayed as a new element and therefore from the top but in the middle. If I do it to the second, the sixth mirrors the second and so on. In practice it seems that the views are linked by 5 in 5.
Here is my simple code:
<CarouselView ItemsSource="{Binding Monkeys}"
HorizontalScrollBarVisibility="Never" >
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical" Spacing="0">
<ScrollView VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never" >
<StackLayout>
<Image
Source="{Binding ImageUrl}" HeightRequest="350"
Aspect="AspectFill" />
<Label Text="{Binding Name}"
LineBreakMode="TailTruncation"/>
<Label Text="{Binding Details}" FontSize="35" />
<Label Text="{Binding Details}" FontSize="35" TextColor="Aqua"/>
<Label Text="{Binding Details}" FontSize="35" TextColor="Fuchsia"/>
<Label Text="{Binding Details}" FontSize="35" TextColor="OliveDrab"/>
</StackLayout>
</ScrollView>
<Label Text="Fixed Button" BackgroundColor="Red" TextColor="White" HeightRequest="50" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
GIF dimostration

Xamarin Forms Horizontal / Vertical options don' seem to be working

I have the following XAML in my Xamarin Forms project
<StackLayout x:Name="slFullPage" Orientation="Vertical" HorizontalOptions="Fill" VerticalOptions="FillAndExpand" Margin="0,0,0,0" BackgroundColor="AliceBlue">
<localapp:PageHeader x:Name="pgHeader" VerticalOptions="Start" HorizontalOptions="Fill" />
<combobox:SfComboBox x:Name="cmbLanguage" DataSource="{Binding LangaugesByAppLanguage}" TextSize="Micro"
TextColor="#283655" SelectionChanged="cmbLanguage_SelectionChanged"
Watermark="{localapp:Translate SelectValue}" DropDownItemHeight="25" WidthRequest="250" HeightRequest="30"
DropDownTextSize="Micro" BackgroundColor="White" HorizontalOptions="Center" VerticalOptions="Start"
DisplayMemberPath="LanguageName" SelectedValuePath="ISO_639_1_Code">
</combobox:SfComboBox>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="End" BackgroundColor="Aqua">
<buttons:SfButton x:Name="btnCancel" Text="{localapp:Translate Cancel}" HorizontalOptions="Start" VerticalOptions="End" Margin="8,0,4,0"/>
<buttons:SfButton x:Name="btnDone" Text="{localapp:Translate Done}" HorizontalOptions="End" VerticalOptions="End" Margin="4,0,8,0"/>
</StackLayout>
<localapp:AppFooter x:Name="pgFooter" VerticalOptions="End" HorizontalOptions="Fill" />
</StackLayout>
Based on my understanding of the horizontal options that can be specified on an object, I would expect the Cancel button to be at the start of my horizontal stack layout and my Done button to be at the end of the same stack layout.
Additionally, based on the vertical options that can be used, I would expect the stacklayout with the buttons in it as well as my appfoot to appear at the bottom of my slFullPage stack layout. However, neither of those things are happening.
Instead what I get can be seen below:
You can see that the entire page stacklayout is going all the way to the bottom of the screen but my buttons and footer are not at the bottom.
Additinally, you can see the horizontal stack layout (aqua) goes all the way across the screen but the buttons are not positioned based on their horizontal options.
Any ideas?? FYI - I am running the project as a UWP app.
Based on my understanding of the horizontal options that can be specified on an object, I would expect the Cancel button to be at the start of my horizontal stack layout and my Done button to be at the end of the same stack layout.
You could use a AbsoluteLayout to make the buttons positioned anywhere within a view.
<AbsoluteLayout BackgroundColor="LightBlue" HeightRequest="60" VerticalOptions="EndAndExpand">
<Button Text="Cancel" Margin="10,10" BackgroundColor="DarkBlue" TextColor="White"/>
<Button Text="Done" Margin="10,10" AbsoluteLayout.LayoutBounds="1, 0, AutoSize, AutoSize" AbsoluteLayout.LayoutFlags="PositionProportional" BackgroundColor="DarkBlue" TextColor="White"/>
</AbsoluteLayout>
And use the VerticalOptions="EndAndExpand" to make it appears at the end of its parent and expands.
Updated:
I do not know what it was before, but for now, it doesn’t actually fill up the space in the StackLayout. It’s only when the fill option is used, that it will expand to that space.
When you expect the Cancel button to be at the start and the Done button to be at the end of the same stack layout, fill option and expend need to be setted. I use simple example to display.
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand" BackgroundColor="Aqua">
<Button x:Name="btnCancel" Text="Cancel" HorizontalOptions="StartAndExpand" Margin="8,0,4,0"/>
<Button x:Name="btnDone" Text="Done" HorizontalOptions="EndAndExpand" Margin="4,0,8,0"/>
</StackLayout>
And if you do not want space between last two lines in the end, you need a nested stacklayout to do that without space.
Simple code:
<StackLayout BackgroundColor="LightGray">
<StackLayout>
<Entry x:Name="pgHeader" Text="pgHeader" HorizontalOptions="FillAndExpand" />
<Entry x:Name="cmbLanguage" Text="cmbLanguage" WidthRequest="250" HeightRequest="30"
BackgroundColor="Red" HorizontalOptions="CenterAndExpand" ></Entry>
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand">
<StackLayout Orientation="Horizontal" BackgroundColor="Aqua">
<Button x:Name="btnCancel" Text="Cancel" HorizontalOptions="StartAndExpand" Margin="8,0,4,0"/>
<Button x:Name="btnDone" Text="Done" HorizontalOptions="EndAndExpand" Margin="4,0,8,0"/>
</StackLayout>
<Entry x:Name="pgFooter" Text="pgFooter"/>
</StackLayout>
</StackLayout>
You don't want to use a StackLayout (well 2 StackLayout), but a Grid:
It's more convenient for your layout, and it is way more performant.
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinition>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinition>
<localapp:PageHeader Grid.Row="0" x:Name="pgHeader" />
<combobox:SfComboBox Grid.Row="1" x:Name="cmbLanguage" DataSource="{Binding LangaugesByAppLanguage}" TextSize="Micro"
TextColor="#283655" SelectionChanged="cmbLanguage_SelectionChanged"
Watermark="{localapp:Translate SelectValue}" DropDownItemHeight="25" WidthRequest="250"
DropDownTextSize="Micro" BackgroundColor="White" HorizontalOptions="Center"
DisplayMemberPath="LanguageName" SelectedValuePath="ISO_639_1_Code">
</combobox:SfComboBox>
<buttons:SfButton Grid.Row="2" Grid.Column="0"
x:Name="btnCancel" Text="{localapp:Translate Cancel}" Margin="8,0,4,0"/>
<buttons:SfButton Grid.Row="2" Grid.Column="2"
x:Name="btnDone" Text="{localapp:Translate Done}" Margin="4,0,8,0"/>
</Grid>

CardView in Xamarin.Forms

I'm looking for a way to dynamically generate card-like controls that look like these:
I have been doing some search and have found this article that shows you how to implement CardView on a Xamarin.Android project. But I'm using Xamarin.Forms so I can compile for iOS as well.
I also tried to use a ListView with ViewCells and a couple StackLayout tags, but wasn't able to even get close to that, here is the code:
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="300">
<StackLayout>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding UserAvatar}" />
<Label Text="{Binding UserName}" />
</StackLayout>
<Image Source="{Binding BittImage}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I'm pretty new to Xamarin, so if I'm missing something basic, please let me know guys.
You are on the right track. Use a ListView, with a Frame as the root element and a margin, and set the background color of the ListView as appropriate. This should give you the card look. Then you fill in the card as you require.
<ListView x:Name="listView" BackgroundColor="Gray">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="300">
<Frame HasShadow="true" Margin="5">
<StackLayout>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding UserAvatar}" />
<Label Text="{Binding UserName}" />
</StackLayout>
<Image Source="{Binding BittImage}" />
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Resources