Xamarin forms Center NavigationPage title - xaml

I have a problem. I used Navigation.PushAsync(), so now on my second page I have a back arrow in the NavigationBar. Now I want to add a titleview as well, in the middle of the NavigationBar, but it doesn't get centered in exactly the middle, but more to the right, because of the back button.
I already tried to set it in a AbsoluteLayout like this:
<NavigationPage.TitleView>
<AbsoluteLayout>
<Label Text="MyTitle" FontSize="20" AbsoluteLayout.LayoutBounds="0.5, 0.5" AbsoluteLayout.LayoutFlags="PositionProportional" />
</AbsoluteLayout>
</NavigationPage.TitleView>
But still same result :(
How can I fix this?

Remove the back button
<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"
NavigationPage.HasBackButton="False">
Add a custom image and use TapGesture (or you can use FontAwesome or something)
<AbsoluteLayout>
<Image AbsoluteLayout.LayoutBounds="0, 0.5" AbsoluteLayout.LayoutFlags="PositionProportional" WidthRequest="20" HeightRequest="20"
Source="arrow16">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Image.GestureRecognizers>
</Image>
<Label Text="MyTitle" FontSize="20" AbsoluteLayout.LayoutBounds="0.5, 0.5" AbsoluteLayout.LayoutFlags="PositionProportional" />
</AbsoluteLayout>
On tap event pop the page
private async void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
await Navigation.PopAsync();
}

Related

Resume and modify some graphic elements present in another page

I have created a ControlTemplate in the app.xaml, defining the graphic part, only in the cs I would like to take some elements, to which I have given the name, to assign them the click event, but it signals me that they do not exist in the current context .
Someone who could kindly tell me how to please?
Someone, if possible, modify the source of the webview present in the main page, directly from app.xaml.cs
My code in the template is this:`
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="HeaderFooterTemplate"><ContentPresenter />
<StackLayout>
<BoxView HorizontalOptions="FillAndExpand" BackgroundColor="#DDDDDD" HeightRequest="2" Margin="0" />
<ScrollView Orientation="Horizontal">
<Grid RowSpacing="0">
<StackLayout Background="#c9ced6" HeightRequest="120" MinimumHeightRequest="120" Orientation="Horizontal" Grid.Row="0" Spacing="2">
<Grid WidthRequest="100" MinimumHeightRequest="120" BackgroundColor="#373B53" Padding="10" x:Name="Dashboard">
<Image Source="homeArancione" x:Name="imgDashboard" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="30" HeightRequest="30" Grid.Row="0" />
<Label Text="DASHBOARD" TextColor="#c9ced6" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
</Grid></Grid>
And in the reference page I recall it like this:
ControlTemplate="{StaticResource HeaderFooterTemplate}"
Graphically it works, but in the cs is I can't modify the texts to the labels or assign click events to the elements because it tells me that they don't exist in the current context
If you want to change the text or trigger the click event of the label in ControlTemplate, you could use the GestureRecognizers. The x:Name could not be found in the ControlTemplate directly.
<ControlTemplate x:Key="HeaderFooterTemplate">
<!--<ContentPresenter />-->
<StackLayout>
<BoxView HorizontalOptions="FillAndExpand" BackgroundColor="#DDDDDD" HeightRequest="2" Margin="0" />
<ScrollView Orientation="Horizontal">
<Grid RowSpacing="0">
<StackLayout Background="#c9ced6" HeightRequest="120" MinimumHeightRequest="120" Orientation="Horizontal" Grid.Row="0" Spacing="2">
<Grid WidthRequest="100" MinimumHeightRequest="120" BackgroundColor="#373B53" Padding="10" x:Name="Dashboard">
<Image Source="homeArancione" x:Name="imgDashboard" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="30" HeightRequest="30" Grid.Row="0" />
<Label Text="DASHBOARD" TextColor="#c9ced6" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
</Label.GestureRecognizers>
</Label>
</Grid>
</StackLayout>
</Grid>
</ScrollView>
</StackLayout>
</ControlTemplate>
Code behind: App.xaml.cs
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
Console.WriteLine("-----------");
var label = sender as Label;
label.Text = "Hello";
}
Update:
update the text of the label as soon as the page loads, without
having to click
Xamarin provide GetTemplateChild to get a named element from a template. The GetTemplateChild method should only be called after the OnApplyTemplate method has been called. If you want to call the OnApplyTemplate method, this template should be added for the contentpage.
You could refer to the thread i done before.
Xamarin SwipeView Open Left Item In ControlTemplate

Is there a way to limit the boundaries of a drag event to the size of the screen?

I'm making a weather application and on one of the pages, users can save cities to quickly look up the weather for that city. I also want them to be able to delete a city in the list by pressing and holding and then dragging it to the delete button on the bottom of the screen.
The problem is that the label for the city name is the width of the entire screen and when you press and hold a city, you automatically grab the center of this label. Because of this, when you press the city name to much to the left of the label, the name disappears outside of the screen.
I can think of 2 possible solutions; make the screen have some kind of boundaries so nothing can disappear or make the label the width of the text within. But I can't find any of these solutions online. Does someone know how to do this or maybe has another solution?
This is the code for the xaml file.
<StackLayout>
<CollectionView x:Name="CitiesListView"
ItemsSource="{Binding Cities}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10" x:DataType="model:City">
<Label Text="{Binding name}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListCityTextStyle}"
FontSize="16" />
<StackLayout.GestureRecognizers>
<DragGestureRecognizer DragStartingCommand="{Binding Path=DragStartingCommand, Source={RelativeSource AncestorType={x:Type local:CitiesViewModel}}}" DragStartingCommandParameter="{Binding .}"/>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:CitiesViewModel}}, Path=CityTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<StackLayout HorizontalOptions="Center" VerticalOptions="FillAndExpand" Padding="5,10,5,10">
<StackLayout.GestureRecognizers>
<DropGestureRecognizer DropCommand="{Binding DropOverCommand}"/>
</StackLayout.GestureRecognizers>
<Image HeightRequest="40"
WidthRequest="40"
Source="trash_icon.png"
HorizontalOptions="EndAndExpand"/>
</StackLayout>
</StackLayout>
And this is the code for the drag and drop commands
public Command DragStartingCommand => new Command<City>((param) =>
{
var dur = TimeSpan.FromSeconds(0.1);
Vibration.Vibrate(dur);
_dragCity = param;
});
public Command DropOverCommand => new Command(() =>
{
if (Cities.Contains(_dragCity))
{
Cities.Remove(_dragCity);
removeCity(_dragCity);
}
});
public async void removeCity(City city)
{
await DataStore.DeleteCityAsync(city.id);
}
private City _dragCity;
Here is also a link to a video maybe better understand what I am talking about. Video
You could try to set the DragGestureRecognizer for the Label instead of StackLayout. A simple example for your reference. The text of Label would on the point which you pressed.
Xaml:
private async void OnDropGestureRecognizerDragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Copy;
}
private async void OnDropGestureRecognizerDrop(object sender, DropEventArgs e)
{
await DisplayAlert("Correct", "Congratulations!", "OK");
//await DisplayAlert("Incorrect", "Better luck next time.", "OK");
}
Code behind:
<StackLayout Margin="20">
<Label Text="Answer the following question by dragging your answer to the Entry." />
<Label Text="What's 2+2?" />
<Grid ColumnDefinitions="0.5*, 0.5*"
Margin="0,20,0,0">
<Label Text="3"
HorizontalOptions="Center">
<Label.GestureRecognizers>
<DragGestureRecognizer />
</Label.GestureRecognizers>
</Label>
<Label Grid.Column="1"
Text="4"
HorizontalOptions="Center">
<Label.GestureRecognizers>
<DragGestureRecognizer />
</Label.GestureRecognizers>
</Label>
</Grid>
<Entry Margin="0,20,0,0"
Placeholder="Drag your answer here">
<Entry.GestureRecognizers>
<DropGestureRecognizer DragOver="OnDropGestureRecognizerDragOver"
Drop="OnDropGestureRecognizerDrop" />
</Entry.GestureRecognizers>
</Entry>
</StackLayout>

Not able to close the popup on click event in Xamarin Forms

I have used Rg.Plugins.Popup.
I have aligned close button which is aligned at top right corner 50% outside the window from right and top side as shown in below image.
Now it is showing as per expected design but issue is when I tap on it, only inward part of close button get clicked and outward part is not clickable. So not able to close popup till the time we click that inward part of Close button.
I am sharing my code for more idea.
<ScrollView Orientation="Horizontal">
<AbsoluteLayout HorizontalOptions="Center"
VerticalOptions="Center"
Padding="0,0,0,0"
Margin="0,0,0,0"
Opacity="1">
<Frame AbsoluteLayout.LayoutBounds="0,0,1,1"
IsClippedToBounds="True"
AbsoluteLayout.LayoutFlags="All"
HasShadow="False"
x:Name="outframe"
Margin="0"
CornerRadius="15"
Padding="0"
OutlineColor="#ffffff"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal"
x:Name="stkVideo"
Padding="0">
<Image x:Name="ximage"
Aspect="AspectFill"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
BackgroundColor="#4A4541" />
<video:VideoPlayer x:Name="trainingPlayer"
DisplayControls="True"
FillMode="ResizeAspectFill"
FlowDirection="LeftToRight"
Volume="100"
Grid.Row="0"
IsVisible="false">
</video:VideoPlayer>
</StackLayout>
</Frame>
<ContentView AbsoluteLayout.LayoutBounds="0.50, 0.50, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional">
<Image Source="Play.png"
HeightRequest="{OnIdiom Phone=70,Tablet=85}"
WidthRequest="{OnIdiom Phone=70,Tablet=85}"
Aspect="AspectFit"
VerticalOptions="Center"
HorizontalOptions="Center"
x:Name="icnplay" />
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_1" />
</ContentView.GestureRecognizers>
</ContentView>
<ContentView AbsoluteLayout.LayoutBounds="1.04, -0.09, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional" >
<Image Source="close.png"
HeightRequest="{OnIdiom Phone=35,Tablet=45}"
WidthRequest="{OnIdiom Phone=35,Tablet=45}"
Aspect="AspectFit">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Image.GestureRecognizers>
</Image>
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</ContentView.GestureRecognizers>
</ContentView>
</AbsoluteLayout>
</ScrollView>
What code changes do I need to do so that popup get close when user will click on Close button part which is outside the window as well?
The issue is the close button lies outside the bounds of the <AbsoluteLayout>. One solution involves a few steps:
Make the AbsoluteLayout larger by some amount
Add a margin to the video player Frame equal to how much larger the AbsoluteLayout was made
Update the position of the close button to remain in the top right corner of the video player Frame
Now the close button is contained within the AbsoluteLayout and the entire close button area will receive and raise events for taps/clicks.
I guess that you want to achieve this:
Clicking outside the yellow frame will close the everything.
The red part has a GestureRecognizer
You can achieve this by using a Grid or a Absolute layout, these views allow you to "stack" or add layers to the UI.
Code example:
<AbsoluteLayout
BackgroundColor="Green"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All">
<Button Clicked="Button_Clicked" Text="Coso" />
<Button Clicked="Button_Clicked_1" Text="Show popup" />
</StackLayout>
<Frame
x:Name="closeFrame"
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Red"
IsVisible="false">
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Tapped="TapGestureRecognizer_Tapped" />
</Frame.GestureRecognizers>
</Grid>
<Frame
x:Name="popupGrid"
AbsoluteLayout.LayoutBounds="0.5,0.5,0.5,0.5"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Yellow"
IsVisible="false">
<Label Text="Close ouside this" TextColor="Black" />
</Frame>
</AbsoluteLayout>
In code behind you turn the visibile on/off of the element

how to put constant height for my signature pad irrespective of orientation?

In a xamarin app, i have created a signature pad , and i have kept margin like
i want to keep a permanent heigh for the signature area irrespective of device and orientation,
i am not xamarin developer, And i dont have idea about xaml, still I tried Margin="200,200,200,200" , but it behaves weirdly when i change orientation.
in ipad in landscape mode the area is not at all visible.
<?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:signaturePad="clr-namespace:Acr.XamForms.SignaturePad;assembly=Acr.XamForms.SignaturePad"
x:Class="watebook.Clients.Mobile.Views.CaptureSignature"
BackgroundColor="{StaticResource PageBackgroundColor}">
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<ContentView Style="{StaticResource PageHeaderBodySeparator}" />
<signaturePad:SignaturePadView
Margin="200,200,200,200"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
x:Name="padView"
BackgroundColor="{StaticResource SignaturePadBackgroundColor}"
CaptionText="Please sign here"
CaptionTextColor="{StaticResource SignaturePadCaptionTextColor}"
PromptText="."
SignatureLineColor="{StaticResource SignaturePadSignatureLineColor}"
StrokeColor="{StaticResource SignaturePadSignatureStrokeColor}"
StrokeWidth="2"
ClearText="" />
<Button Text="SAVE SIGNATURE" Clicked="Button_OnClicked" BackgroundColor="#ffd300" TextColor="Black" x:Name="SaveButton" BorderColor="Black" Margin="0,10,0,300" />
</StackLayout>
<ContentView Style="{StaticResource ProcessIndicatorContentViewStyle}" x:Name="ActivityCameraIndicators" IsVisible="False" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<Label Style="{x:StaticResource ProcessIndicatorLabelStyle}" Text="Processing" x:Name="ActivityIndicatorLable" />
</ContentView>
</AbsoluteLayout>
</ContentPage>
How to keep a permanent height for my signature pad?
use HeightRequest
<signaturePad:SignaturePadView HeightRequest="200" ... />

Xamarin Forms Delay in Navigation

I am working on a Xamarin Forms Project and stuck with an issue, where I want to open some popups. As Forms does not have in build Popups so, I have different XAML pages and I’m loading them inside my MainPage.xaml and changing the visibility when required.
Popup_1.xaml
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml
x:Class="ABC.Views.Popup_1">
<StackLayout >
<Label Text="{Binding FirstName}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" Font="Large" TextColor="Black" />
</StackLayout>
</StackLayout>
I have many layouts like Popup_1 which I want them to be shown as popup. Here’s my MainPage.xaml here contains 3 popup layouts.
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPagexmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml
xmlns:controls="clr-namespace:ABC.Views;assembly=ABC"
x:Class="ABC.Views.MainPage">
<AbsoluteLayout BackgroundColor="Transparent" Padding="10" IsVisible="{Binding ShowPopup_1}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" >
<StackLayout Orientation="Horizontal" BackgroundColor="Transparent" AbsoluteLayout.LayoutBounds="0.5, 0.5, -1, -1" AbsoluteLayout.LayoutFlags="PositionProportional" >
<controls:Popup_1 />
</StackLayout>
</AbsoluteLayout>
<AbsoluteLayout BackgroundColor="Transparent" Padding="10" IsVisible="{Binding ShowPopup_2}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" >
<StackLayout Orientation="Horizontal" BackgroundColor="Transparent" AbsoluteLayout.LayoutBounds="0.5, 0.5, -1, -1" AbsoluteLayout.LayoutFlags="PositionProportional" >
<controls:Popup_2 />
</StackLayout>
</AbsoluteLayout>
<AbsoluteLayout BackgroundColor="Transparent" Padding="10" IsVisible="{Binding ShowPopup_3}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" >
<StackLayout Orientation="Horizontal" BackgroundColor="Transparent" AbsoluteLayout.LayoutBounds="0.5, 0.5, -1, -1" AbsoluteLayout.LayoutFlags="PositionProportional" >
<controls:Popup_3 />
</StackLayout>
</AbsoluteLayout>
</ContentPage>
The problem is when I am trying to navigate to Mainpage.xaml it taking a lot of time to navigate. Is there any standard solution for this issue? or How can I deal with this delay ?
Note: I’m using MVVM binding pattern to change the visibility of layouts.
You're right about to use ContentPage to customize your own popup dialog, but the normal way to show this custom dialog is not setting the visibility of the parent element of your dialog. We need to display it using PushModalAsync and dismiss it using PopModalAsync.
For code sample you can refer to PushModalAsync or PopModalAsync.
I'm not sure what blocks your UI to cause the delay of navigation since you didn't post any code behind of your dialog. Anyway, you can try to push and pop a modal page and see if this helps.
As Forms does not have in build Popups
Refer this page of documentation
https://developer.xamarin.com/guides/xamarin-forms/user-interface/navigation/pop-ups/