How to create a ScrollView in this layout? - xaml

I need to create a ScrollView in this layout but the problem is that my control occupies the entire screen and I don't know how to make it occupy only the size it has. This is the functionality of the control
I need it not to fill the entire screen and only its own size to be able to add more things to the layout
This is the XAML of my control:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="ControlProject.CustomControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="CustomView">
<ContentView.Content>
<AbsoluteLayout>
<!-- ================This is the entry that must be in the bottom================ -->
<StackLayout
x:Name="STACK"
AbsoluteLayout.LayoutBounds="0,1,1,0.07"
AbsoluteLayout.LayoutFlags="All"
Orientation="Horizontal">
<Frame
Margin="0,0,0,2"
Padding="0,0,0,0"
BackgroundColor="{Binding Source={x:Reference CustomView}, Path=FrameColor}"
BorderColor="{Binding Source={x:Reference CustomView}, Path=BorderColor}"
CornerRadius="{Binding Source={x:Reference CustomView}, Path=CornerRadius}"
HasShadow="False"
HorizontalOptions="FillAndExpand">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ImageButton
Grid.Column="0"
Margin="5,0,0,0"
BackgroundColor="Transparent"
Clicked="Open"
HeightRequest="25"
HorizontalOptions="Start"
Source="{Binding Source={x:Reference CustomView}, Path=LeftSideIcon}" />
<Entry
x:Name="EntryControl"
Grid.Column="1"
Margin="0,0,55,0"
HeightRequest="25"
HorizontalOptions="FillAndExpand"
Keyboard="Chat"
Placeholder="{Binding Source={x:Reference CustomView}, Path=Placeholder}"
Text="{Binding EntryText}"
TextColor="{Binding Source={x:Reference CustomView}, Path=EntryTextColor}" />
<ImageButton
Grid.Column="1"
Margin="0,0,40,0"
BackgroundColor="Transparent"
Command="{Binding Source={x:Reference CustomView}, Path=DeleteMsgCommand}"
HeightRequest="25"
HorizontalOptions="End"
Source="{Binding Source={x:Reference CustomView}, Path=DeleteMessageIcon}" />
<ImageButton
Grid.Column="1"
Margin="0,0,10,0"
Padding="1"
BackgroundColor="Transparent"
Command="{Binding Source={x:Reference CustomView}, Path=InsertImgCommand}"
HeightRequest="25"
HorizontalOptions="End"
Source="{Binding Source={x:Reference CustomView}, Path=InsertImgIcon}" />
</Grid>
</Frame>
<ImageButton
Margin="0,0,5,2"
Padding="15,0,10,0"
BackgroundColor="{Binding Source={x:Reference CustomView}, Path=SendBtnColor}"
Command="{Binding Source={x:Reference CustomView}, Path=SendMsgCommand}"
CornerRadius="30"
HeightRequest="45"
HorizontalOptions="End"
Source="{Binding Source={x:Reference CustomView}, Path=RightSideIcon}"
WidthRequest="45" />
</StackLayout>
<!-- ================This is what it moves up================ -->
<StackLayout
x:Name="frameemojis"
AbsoluteLayout.LayoutBounds="0,1,1,0.43"
AbsoluteLayout.LayoutFlags="All"
TranslationY="{Binding Height, Source={x:Reference frameemojis}}">
<Frame>
<CollectionView
Margin="-10,-15,-10,-10"
HeightRequest="270"
ItemsSource="{Binding Source={x:Reference CustomView}, Path=EmojiItemSource}"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal" Span="5" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<ImageButton
Padding="5"
BackgroundColor="Transparent"
Command="{Binding Source={x:Reference CustomView}, Path=EmojiTappedCommand}"
CommandParameter="{Binding EmojiMethodCommand}"
HeightRequest="44"
Source="{Binding EmojiSource}"
WidthRequest="44" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Frame>
<!-- ============== -->
</StackLayout>
</AbsoluteLayout>
</ContentView.Content>
</ContentView>
MainPage.xaml (this is where I want to add the ScrollView):
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="App24.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:fav="clr-namespace:ControlProject;assembly=ControlProject">
<AbsoluteLayout>
<!-- This is where I want to add the scrollview -->
<StackLayout
AbsoluteLayout.LayoutBounds="0,1,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="#4DFF0000">
<fav:CustomControl
x:Name="entrycontrol"
BorderColor="{Binding EntryBorderColor}"
CornerRadius="{Binding EntryRadius}"
DeleteMessageIcon="crossblack.png"
DeleteMsgCommand="{Binding DeleteMsgCommand}"
EmojiItemSource="{Binding EmojiList}"
EmojiTappedCommand="{Binding EmojiTappedCommand}"
EntryTextColor="{Binding TextColor}"
FrameColor="{Binding EntryBGColor}"
InsertImgCommand="{Binding InsertImgCommand}"
InsertImgIcon="insertimage.png"
LeftSideIcon="icon.png"
Placeholder="Escribddame"
RightSideIcon="send.png"
SendBtnColor="{Binding SendBtnColor}"
SendMsgCommand="{Binding SendMsgCommand}" />
</StackLayout>
</AbsoluteLayout>
</ContentPage>
[EDITED]
Method on code behind control:
bool isShow;
const double layoutPropHeightMax = 0.45;
const double layoutPropHeightMin = 0.06;
private void Button_Clicked(object sender, EventArgs e)
{
if (!isShow)
{
//show the keyboard
Device.BeginInvokeOnMainThread(async () =>
{
var height = layoutPropHeightMin;
while (height < layoutPropHeightMax)
{
await Task.Delay(1);
height += 0.04;
AbsoluteLayout.SetLayoutBounds(bottomBar, new Rectangle(0.5, 1.0, 1.0, height));
}
});
}
else
{
// hide the keyboard
Device.BeginInvokeOnMainThread(async () =>
{
var height = layoutPropHeightMax;
while (height > layoutPropHeightMin)
{
await Task.Delay(1);
height -= 0.04;
AbsoluteLayout.SetLayoutBounds(bottomBar, new Rectangle(0.5, 1.0, 1.0, height));
}
});
}
isShow = !isShow;
}
Control XAML:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="ControlProject.CustomControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="CustomView">
<AbsoluteLayout AbsoluteLayout.LayoutBounds="0,1,1,1" BackgroundColor="White">
<StackLayout
x:Name="bottomBar"
AbsoluteLayout.LayoutBounds="0.5,1,1.0,0.07"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Olive">
<StackLayout
x:Name="STACK"
AbsoluteLayout.LayoutBounds="0,1,1,0.07"
AbsoluteLayout.LayoutFlags="All"
Orientation="Horizontal">
<Frame
Margin="0,0,0,2"
Padding="0,0,0,0"
BackgroundColor="{Binding Source={x:Reference CustomView}, Path=FrameColor}"
BorderColor="{Binding Source={x:Reference CustomView}, Path=BorderColor}"
CornerRadius="{Binding Source={x:Reference CustomView}, Path=CornerRadius}"
HasShadow="False"
HorizontalOptions="FillAndExpand">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ImageButton
Grid.Column="0"
Margin="5,0,0,0"
BackgroundColor="Transparent"
Clicked="Button_Clicked"
HeightRequest="25"
Source="{Binding Source={x:Reference CustomView}, Path=LeftSideIcon}" />
<Entry
x:Name="EntryControl"
Grid.Column="1"
Margin="0,0,55,0"
HeightRequest="25"
HorizontalOptions="FillAndExpand"
Keyboard="Chat"
Placeholder="{Binding Source={x:Reference CustomView}, Path=Placeholder}"
Text="{Binding EntryText}"
TextColor="{Binding Source={x:Reference CustomView}, Path=EntryTextColor}" />
<ImageButton
Grid.Column="1"
Margin="0,0,40,0"
BackgroundColor="Transparent"
Command="{Binding Source={x:Reference CustomView}, Path=DeleteMsgCommand}"
HeightRequest="25"
HorizontalOptions="End"
Source="{Binding Source={x:Reference CustomView}, Path=DeleteMessageIcon}" />
<ImageButton
Grid.Column="1"
Margin="0,0,10,0"
Padding="1"
BackgroundColor="Transparent"
Command="{Binding Source={x:Reference CustomView}, Path=InsertImgCommand}"
HeightRequest="25"
HorizontalOptions="End"
Source="{Binding Source={x:Reference CustomView}, Path=InsertImgIcon}" />
</Grid>
</Frame>
<ImageButton
Margin="0,0,5,2"
Padding="15,0,10,0"
BackgroundColor="{Binding Source={x:Reference CustomView}, Path=SendBtnColor}"
Command="{Binding Source={x:Reference CustomView}, Path=SendMsgCommand}"
CornerRadius="30"
HeightRequest="45"
HorizontalOptions="End"
Source="{Binding Source={x:Reference CustomView}, Path=RightSideIcon}"
WidthRequest="45" />
</StackLayout>
<!-- ================This is what it moves up================ -->
<StackLayout
x:Name="frameemojis"
AbsoluteLayout.LayoutBounds="0,1,1,0.43"
AbsoluteLayout.LayoutFlags="All"
TranslationY="{Binding Height, Source={x:Reference frameemojis}}">
<Frame>
<CollectionView
Margin="-10,-15,-10,-10"
HeightRequest="270"
ItemsSource="{Binding Source={x:Reference CustomView}, Path=EmojiItemSource}"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal" Span="5" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<ImageButton
Padding="5"
BackgroundColor="Transparent"
Command="{Binding Source={x:Reference CustomView}, Path=EmojiTappedCommand}"
CommandParameter="{Binding EmojiMethodCommand}"
HeightRequest="44"
Source="{Binding EmojiSource}"
WidthRequest="44" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Frame>
<!-- ============== -->
</StackLayout>
</StackLayout>
</AbsoluteLayout>
</ContentView>
This is how I want to make it

In the ContentPage because you set the height of Stacklayout as the whole screen
AbsoluteLayout.LayoutBounds="0,1,1,1"
So it will be an expected result .
Actually , in your case you could implement the effect without using ScrollView .
in ContentPage
<AbsoluteLayout BackgroundColor="White" AbsoluteLayout.LayoutBounds="0,1,1,1">
<!-- -->
<Button Clicked="Button_Clicked" Text="Test" AbsoluteLayout.LayoutBounds="0.5,0.3,0.2,0.05" AbsoluteLayout.LayoutFlags="All" />
<StackLayout x:Name="bottomBar" BackgroundColor="Olive" AbsoluteLayout.LayoutBounds="0.5,1.0,1.0,0.04" AbsoluteLayout.LayoutFlags="All">
<!-- put the content of emoji keyboard and entry here -->
</StackLayout>
</AbsoluteLayout>
In Code behind
bool isShow;
const double layoutPropHeightMax = 0.45;
const double layoutPropHeightMin = 0.06;
//you could set the height here as you want
private void Button_Clicked(object sender, EventArgs e)
{
if(!isShow)
{
//show the keyboard
Device.BeginInvokeOnMainThread(async () =>
{
var height = layoutPropHeightMin;
while (height < layoutPropHeightMax)
{
await Task.Delay(1);
height += 0.04;
AbsoluteLayout.SetLayoutBounds(bottomBar, new Rectangle(0.5, 1.0,1.0, height));
}
});
}
else
{
// hide the keyboard
Device.BeginInvokeOnMainThread(async () =>
{
var height = layoutPropHeightMax;
while (height > layoutPropHeightMin)
{
await Task.Delay(1);
height -= 0.04;
AbsoluteLayout.SetLayoutBounds(bottomBar, new Rectangle(0.5, 1.0, 1.0, height));
}
});
}
isShow = !isShow;
}
And in Custom Control let the Entry and Keyboard fill the whole StackLayout .

Related

Xamarin Listview cannot scroll to bottm

I modify the sample https://learn.microsoft.com/zh-tw/samples/xamarin/xamarin-forms-samples/userinterface-xaminals/ ,
replace the collectionview with listview . after replacing I found the listview cannot scroll to bottom (there are total 17 items , but only show 6 items)
This error only happen on Android,but it works well on IOS.
How to solve this problem?
<?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:controls="clr-namespace:Xaminals.Controls"
xmlns:data="clr-namespace:Xaminals.Data"
x:Class="Xaminals.Views.MonkeysPage"
Title="Monkeys">
<RelativeLayout
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Vertical"
VerticalOptions="FillAndExpand"
Padding="10">
<ListView ItemsSource="{x:Static data:MonkeyData.Monkeys}"
x:Name="CollectionView1"
RowHeight="100">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid VerticalOptions="CenterAndExpand" Padding = "20, 0" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image
Grid.RowSpan="2"
Aspect="AspectFill"
HeightRequest="60"
Source="{Binding ImageUrl}"
WidthRequest="60" />
<Label
Grid.Row="0"
Grid.Column="1"
FontAttributes="Bold"
Text="{Binding Name}" />
<Label
Grid.Row="1"
Grid.Column="1"
FontAttributes="Italic"
Text="{Binding Price}"
VerticalOptions="End" />
<Image Grid.Row="2" Grid.Column="0" Source="bear.png" HeightRequest="25" WidthRequest="25">
<Image.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
<ActivityIndicator x:Name="activityIndicator" Color="Red" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.33}" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height,Factor=0.33}" />
</RelativeLayout>
</ContentPage>
The solution is change the RelativeLayout to Stacklayout:
<StackLayout
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Vertical"
VerticalOptions="FillAndExpand"
Padding="10">
<ListView ItemsSource="{x:Static data:MonkeyData.Monkeys}"
x:Name="CollectionView1"
RowHeight="100">
.....
</ListView>
</StackLayout>
</StackLayout>
If you want to use RelativeLayout, you need to use XConstraint, YConstraint,WidthConstraint,HeightConstraint to layout the child view instead of VerticalOptions="FillAndExpand", HorizontalOptions="FillAndExpand".

First-time user onboarding with Xamarin.Forms

I am implementing a first-time user onboarding in a Xamarin.Forms application like the one on the image below:
Please, how can I quickly do that?
Thank you in advance.
Do you want to achieve the result like following GIF?
You can use CarouselView and IndicatorView to achieve it.
Here is layout code.I dont adjust the layout like yours, you can adjust it by yourself, If you want to make Next and Skip Button over float the CarouselView, you can use AbsoluteLayout
<StackLayout Margin="10">
<CarouselView x:Name="myCarouselView" ItemsSource="{Binding Monkeys}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="50"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Skip" Grid.Column="0" BackgroundColor="Transparent" Clicked="Button_Clicked"></Button>
<Button Text="Next" Grid.Column="1" BackgroundColor="Transparent" Clicked="Button_Clicked_1"></Button>
</Grid>
<IndicatorView x:Name="indicatorView"
MaximumVisible="6"
Margin="0,0,0,40"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" />
</StackLayout>
Here is layout bakground code.
public partial class BasicIndicatorViewPage : ContentPage
{
int monkeyCount;
public BasicIndicatorViewPage()
{
InitializeComponent();
MonkeysViewModel monkeysViewModel= new MonkeysViewModel();
monkeyCount = monkeysViewModel.Monkeys.Count;
BindingContext = monkeysViewModel;
}
private void Button_Clicked(object sender, System.EventArgs e)
{
Navigation.PushAsync(new Page1());
Navigation.RemovePage(this);
}
private void Button_Clicked_1(object sender, System.EventArgs e)
{
if (myCarouselView.Position < monkeyCount-1)
{
myCarouselView.Position += 1;
}
else
{
Navigation.PushAsync(new Page1());
Navigation.RemovePage(this);
}
}
}
Here is my demo, you can download it.
https://github.com/851265601/XFormsCarouselView-IndicatorViewLoginPage
If you want to put the indicatorView and Button in the same line like this screenshot.
You can use this layout(indicatorView to the Grid).
<StackLayout Margin="10">
<CarouselView x:Name="myCarouselView" ItemsSource="{Binding Monkeys}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="50"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Skip" Grid.Column="0" BackgroundColor="Transparent" Clicked="Button_Clicked"></Button>
<IndicatorView x:Name="indicatorView"
MaximumVisible="6"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" Grid.Column="1" />
<Button Text="Next" Grid.Column="2" BackgroundColor="Transparent" Clicked="Button_Clicked_1"></Button>
</Grid>
</StackLayout>
You could use the offical Xamarin.Forms CarouselView but that's still in preview. You could also potentially look at the Sharpnado's solution with HorizontalListView. Your third option would be to use Alex Rainman's CarouselView.

Xamarin ImageButton goes invisible after clicked

I have an image button which when I click I want to change its Source (an empty star to a filled one) for the ratings.
My XAML:
<StackLayout Grid.Row="1" Orientation="Horizontal" Spacing="0">
<ImageButton Source="star_empty.png"
HeightRequest="40"
WidthRequest="40"
VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
x:Name="star1"
BackgroundColor="Transparent"
Clicked="ImageButton_Clicked" />
<ImageButton Source="star_empty.png"
HeightRequest="40"
WidthRequest="40"
VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
x:Name="star2"
BackgroundColor="Transparent"
Clicked="ImageButton_Clicked2" />
<ImageButton Source="star_empty.png"
HeightRequest="40"
WidthRequest="40"
VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
x:Name="star3"
BackgroundColor="Transparent"
Clicked="ImageButton_Clicked3" />
<ImageButton Source="star_empty.png"
HeightRequest="40"
WidthRequest="40"
x:Name="star4"
VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
BackgroundColor="Transparent"
Clicked="ImageButton_Clicked4" />
<ImageButton Source="star_empty.png"
HeightRequest="40"
WidthRequest="40"
x:Name="star5"
VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
BackgroundColor="Transparent"
Clicked="ImageButton_Clicked5" />
</StackLayout>
The View class:
private void ImageButton_Clicked(object sender, EventArgs e)
{
star1.Source = "star_full.png";
int rating = 1;
}
What could be the issue? The Source does change, it just blinks then goes invisible. I set the isVisible property to true, that doesn't help.
Define the type of ImageSource you are using; file, resource, uri, stream:
Example:
star1.Source = ImageSource.FromResource("star_full.png");
Update:
<StackLayout Grid.Row="1" Orientation="Horizontal" Spacing="0">
<ImageButton x:Name="star1" Source="star_off.png" BackgroundColor="Transparent" Clicked="ImageButton_Clicked"/>
<ImageButton x:Name="star2" Source="star_off.png" BackgroundColor="Transparent" Clicked="ImageButton_Clicked"/>
<ImageButton x:Name="star3" Source="star_off.png" BackgroundColor="Transparent" Clicked="ImageButton_Clicked"/>
<ImageButton x:Name="star4" Source="star_off.png" BackgroundColor="Transparent" Clicked="ImageButton_Clicked"/>
<ImageButton x:Name="star5" Source="star_off.png" BackgroundColor="Transparent" Clicked="ImageButton_Clicked"/>
</StackLayout>
Code behind:
void ImageButton_Clicked(object sender, System.EventArgs e)
{
(sender as ImageButton).Source = ImageSource.FromFile("star_on.png");
}

How to reuse the same view in Xamarin? XAML

So I got this code that I need to re-use on more or less all my pages, but I'm getting kinda tired of changing one page and having to do the same thing in 10 or more places, are there any better way to do this?
Using Xamarin.Forms. Maybe it is possible to do this with a custom controller or some other way with markup extension to inside a stacklayout do a x:static reference to it?
<!--#region BOTTOM Navigation Bar-->
<!-- Theme Colored bar-->
<StackLayout Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Padding="0,0,0,0" Spacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Orientation="Horizontal" BackgroundColor="{StaticResource ThemeBkColor}" >
</StackLayout>
<!-- Bottom Menu bar -->
<StackLayout Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Padding="0,3,0,3" Spacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Orientation="Horizontal" BackgroundColor="{StaticResource ThemeBkColorBottomBar}" >
<!-- Left -->
<StackLayout Padding="15,0,0,0" Spacing="10" VerticalOptions="FillAndExpand" HorizontalOptions="StartAndExpand" Orientation="Horizontal" >
<StackLayout Orientation="Vertical" VerticalOptions="Center" HorizontalOptions="CenterAndExpand" Spacing="2">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CmdGoToCheckUpdates}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image Source="updates.png" HeightRequest="35" WidthRequest="35" HorizontalOptions="Center" />
<Label Text="Updates" HorizontalOptions="Center" Style="{StaticResource BottomMenuBtnText}" />
</StackLayout>
</StackLayout>
<!-- Center -->
<StackLayout Padding="0,0,0,0" Orientation="Horizontal" Spacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" >
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="0,0,0,0" RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Orientation="Vertical" VerticalOptions="Center" HorizontalOptions="FillAndExpand" Spacing="2" >
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CmdGoToCatalog}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image Source="catalogues.png" HeightRequest="35" WidthRequest="35" HorizontalOptions="Center">
</Image>
<Label Text="Catalog" HorizontalOptions="Center" Style="{StaticResource BottomMenuBtnText}" />
</StackLayout>
<StackLayout Grid.Row="0" Grid.Column="1" Orientation="Vertical" VerticalOptions="Center" HorizontalOptions="FillAndExpand" Spacing="2">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CmdGoToPresentation}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image Source="display.png" HeightRequest="35" WidthRequest="35" HorizontalOptions="Center" >
</Image>
<Label Text="Presentations" HorizontalOptions="Center" Style="{StaticResource BottomMenuBtnText}" />
</StackLayout>
<StackLayout Grid.Row="0" Grid.Column="2" Orientation="Vertical" VerticalOptions="Center" HorizontalOptions="FillAndExpand" Spacing="2">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CmdGoToScan}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image Source="scan.png" HeightRequest="35" WidthRequest="35" HorizontalOptions="Center">
</Image>
<Label Text="Scanner" HorizontalOptions="Center" Style="{StaticResource BottomMenuBtnText}" />
</StackLayout>
<StackLayout Grid.Row="0" Grid.Column="3" Orientation="Vertical" VerticalOptions="Center" HorizontalOptions="FillAndExpand" Spacing="2">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CmdGoToSearch}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image Source="Search.png" HeightRequest="35" WidthRequest="35" HorizontalOptions="Center">
</Image>
<Label Text="Search" HorizontalOptions="Center" Style="{StaticResource BottomMenuBtnText}" />
</StackLayout>
</Grid>
</StackLayout>
<!-- Right -->
<StackLayout Padding="0,0,15,0" Spacing="10" VerticalOptions="FillAndExpand" HorizontalOptions="EndAndExpand" Orientation="Horizontal" >
<StackLayout Orientation="Vertical" VerticalOptions="Center" HorizontalOptions="CenterAndExpand" Spacing="2">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CmdGoToLoginLogout}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image Source="logout.png" HeightRequest="35" WidthRequest="35" >
</Image>
<Label Text="Settings" HorizontalOptions="Center" Style="{StaticResource BottomMenuBtnText}" />
</StackLayout>
</StackLayout>
</StackLayout>
<!--#endregion-->
You can create a CustomView and then include that in your Pages.
In order to Achieve that, you create a a YourCustomView.xaml,
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourProject.YourCustomView">
</ContentView>
And, in your Page.xaml you include it
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:YourProject;assembly=YourProject"
x:Class="YourProject.YourPage">
<views:YourCustomView/>
</ContentPage>
The next step is about Binding the properties that you need, for that, you need to create BindableProperties in your CustomView. You can reuse this in all pages that you want.

the tapgesturerecognizers doesn't work for images in the same position xamarin.forms

These are my image:
the green one is over the yellow, I used a grid for it...But it makes that when I tap the green one the tap doesn't work...when they were not in the same position, the green image worked.
this problem happens only in iphone devices
my grid:
<Grid>
<Image BackgroundColor="Yellow" Margin="10,10,0,0" Source="cadastrarCliqueFoto" Grid.Row="0" Grid.Column="0"/>
<Image BackgroundColor="Green" Source="cadastrarVoltar" Margin="10,10,0,0" VerticalOptions="Start" Grid.Row="0" Grid.Column="0" HorizontalOptions="Start">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnClose"/>
</Image.GestureRecognizers>
</Image>
</Grid>
I've already tried 'InputTranparent = true' and it didn't work.
The complete code:
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-
namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
x:Class="neoFly_Montana.PopUp.CadastrarPopup"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
CloseWhenBackgroundIsClicked="False">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="9*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="1" Spacing="0">
<RelativeLayout>
<StackLayout x:Name="stack_cadast" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" BackgroundColor="White"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=1,
Constant=0}"
RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=1,
Constant=0}">
<StackLayout.Spacing>
<OnPlatform x:TypeArguments="x:Double"
iOS="10"/>
</StackLayout.Spacing>
<Grid>
<Image BackgroundColor="Yellow" InputTransparent="true" Margin="10,10,0,0" Source="cadastrarCliqueFoto" Grid.Row="0" Grid.Column="0"/>
<ContentView Grid.Row="0" Grid.Column="0" Margin="10,10,0,0" InputTransparent="true" VerticalOptions="Start" HorizontalOptions="Start">
<Image BackgroundColor="Green" Source="cadastrarVoltar">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnClose"/>
</Image.GestureRecognizers>
</Image>
</ContentView>
<Button Grid.Row="0" BackgroundColor="Blue" Opacity="0.3" Grid.Column="0" Clicked="OnClose"/>
</Grid>
<Entry x:Name="cadastrar_entry_nome" PlaceholderColor="Black" Margin="20, 10, 10, 0" Placeholder="Seu nome completo" HorizontalOptions="Fill"/>
<Entry x:Name="cadastrar_entry_email" PlaceholderColor="Black" Margin="20, 10, 10, 0" Placeholder="E-mail" HorizontalOptions="Fill"/>
<StackLayout Orientation="Horizontal" Margin="20, 10, 10, 0">
<StackLayout Spacing="0">
<Label Text="Data de nascimento" HorizontalOptions="Center" FontSize="Micro"/>
<DatePicker x:Name="cadastrar_date_datanasc"/>
</StackLayout>
<StackLayout Orientation="Horizontal" Padding="0,0,20,0" VerticalOptions="Fill" HorizontalOptions="EndAndExpand" Spacing ="20">
<Image x:Name="cadastrar_img_fem" Scale="1" Source="femDisable">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="FemClique"/>
</Image.GestureRecognizers>
</Image>
<Image x:Name="cadastrar_img_masc" Scale="1" Source="mascDisable">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="MascClique"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
<StackLayout Orientation="Horizontal" Margin="20, 10, 10, 0">
<Picker x:Name="cadastrar_picker_estado" SelectedIndexChanged="PickerEstado_SelectedindexChanged" Title="UF"/>
<ActivityIndicator x:Name="cadastro_cidade_ind" IsVisible="False" IsRunning="True"/>
<Picker x:Name="cadastrar_picker_cidade" IsVisible="False" Title="Cidade"/>
</StackLayout>
<Entry x:Name="cadastrar_entry_senha" PlaceholderColor="Black" IsPassword="true" Margin="20, 10, 10, 10" VerticalOptions="End" Placeholder="Senha" HorizontalOptions="Fill"/>
<Label x:Name="cadastrar_lbl_feedback" FontSize="Micro" HorizontalOptions="Center" Margin="0,0,10,10" TextColor="Red" IsVisible="False"/>
<!--Botão Cadastrar-->
<ContentView Margin="0,20,0,0" Padding="20,20,20,20" BackgroundColor="#700B0F">
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="CadastrarClique"/>
</ContentView.GestureRecognizers>
<Label Text="Cadastrar" VerticalOptions="Center" FontSize="Large" HorizontalOptions="Center" TextColor="White" Style="{StaticResource labelsfont}"/>
</ContentView>
</StackLayout>
<Grid HorizontalOptions="FillAndExpand"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView,
Property=Y,
ElementName=stack_cadast,
Factor=1,
Constant=-42.5}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=1,
Constant=0}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" WidthRequest="75" HeightRequest="75" Grid.Row="0" Grid.Column="1">
<ffimageloading:CachedImage BackgroundColor="Pink" VerticalOptions="End" HorizontalOptions="End" Source="cadastrarPhoto.png" x:Name="cadastrar_foto_perfil">
<ffimageloading:CachedImage.Transformations>
<fftransformations:CircleTransformation />
</ffimageloading:CachedImage.Transformations>
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Tapped="ChamaPickerImage"/>
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
</StackLayout>
</Grid>
</RelativeLayout>
</StackLayout>
Try Absolute layout instead of grid.
<AbsoluteLayout>
<Image BackgroundColor="Yellow" AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All" Margin="10,10,0,0" Source="cadastrarCliqueFoto" />
<Image AbsoluteLayout.LayoutBounds="0,0,30,30" AbsoluteLayout.LayoutFlags="XProportional, YProportional" BackgroundColor="Green" Source="cadastrarVoltar" Margin="10,10,0,0" VerticalOptions="Start" HorizontalOptions="Start">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnClose"/>
</Image.GestureRecognizers>
</Image>
</AbsoluteLayout>
I was facing the same issue. I have put the second Image in ContentView like below and it's working for me.
<Grid>
<Image BackgroundColor="Yellow" Margin="10,10,0,0" Source="cadastrarCliqueFoto" Grid.Row="0" Grid.Column="0"/>
<ContentView Grid.Row="0" Grid.Column="0" Margin="10,10,0,0">
<Image BackgroundColor="Green" Source="cadastrarVoltar" VerticalOptions="Start" HorizontalOptions="Start">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnClose"/>
</Image.GestureRecognizers>
</Image>
</ContentView>
</Grid>
-------- UPDATED -------
XAML code
<Grid>
<Image BackgroundColor="Yellow" Margin="10,10,0,0" Source="cadastrarCliqueFoto" Grid.Row="0" Grid.Column="0"/>
<ContentView Grid.Row="0" Grid.Column="0" Margin="10,10,0,0">
<Image BackgroundColor="Green" Source="cadastrarVoltar" VerticalOptions="Start" HorizontalOptions="Start"/>
</ContentView>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="Close_Tapped"/>
</Grid.GestureRecognizers>
</Grid>
Code behind
void Close_Tapped(object sender, System.EventArgs e)
{
throw new NotImplementedException();
}