Xamarin Android back button is not working - xamarin

I had build a Multipager Xamarin App, but after second page Android back button and Navigation back button is not working.
I had tried Shell Backbuttonbehavior , but with this only Top Navigation back button is working
<Shell.BackButtonBehavior>
<BackButtonBehavior Command="{Binding BackCommand}" IconOverride="back.png" />
</Shell.BackButtonBehavior>
I had tried overriding OnAppearing and OnDisappearing to set Current and pervious navigation but that too is not triggering on thrid page
protected override void OnAppearing()
{
base.OnAppearing();
Shell.Current.Navigating += Current_Navigating;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
Shell.Current.Navigating -= Current_Navigating;
}
private async void Current_Navigating(object sender, ShellNavigatingEventArgs e)
{
if (Models.PatientPlannerData.moveNext == false)
{
Shell.Current.Navigating -= Current_Navigating;
await Shell.Current.GoToAsync("..", true);
}
}
For Navigation from one page to another I am using
await Shell.Current.GoToAsync(nameof(Page2));
Everything is working fine till second page, from third page back button is not triggering

For the Android back button, after compilation the Navigation Bar that we call in Xamarin Forms, turns into the Action Bar for Android during runtime.
Set the toolbar after LoadApplication(new App()); in OnCreate of MainActivity.
AndroidX.AppCompat.Widget.Toolbar toolbar
= this.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
And then overrode OnOptionsItemSelected(). When you press the backbutton on navigation bar, this event would be triggered.
public override bool OnOptionsItemSelected(IMenuItem item)
{
}

Related

Detect Back Arrow Press Of The NavigationPage in Xamarin Forms

Is there any way to detect the press of the back button of the Navigation Page in Xamarin forms?
You can override your navigation page "OnBackButtonPressed" method:
protected override bool OnBackButtonPressed()
{
Device.BeginInvokeOnMainThread(async () =>
{
if (await DisplayAlert("Exit?", "Are you sure you want to exit from this page?", "Yes", "No"))
{
base.OnBackButtonPressed();
await App.Navigation.PopAsync();
}
});
return true;
}
If you are using the shell, you can override the Shell's OnNavigating event:
void OnNavigating(object sender, ShellNavigatingEventArgs e)
{
// Cancel back navigation if data is unsaved
if (e.Source == ShellNavigationSource.Pop && !dataSaved)
{
e.Cancel();
}
}
Update:
OnBackButtonPressed event will get fired ONLY on Android when user press the Hardware back button.
Seems like you are more interested to implement when any page get disappeared you want to do something!
In that case:
You have the page's two methods -
protected override void OnAppearing()
{
base.OnAppearing();
Console.WriteLine("Hey, Im coming to your screen");
}
protected override void OnDisappearing()
{
base.OnDisappearing();
Console.WriteLine("Hey, Im going from your screen");
}
You can override those 2 methods on any page to track when they appear and disappear.
Recent updates to Xamarin forms mean you can now do this in an application made with Shell Navigation for navigation back arrow on both platforms.
Use the Shell.SetBackButtonBehavior method, for example running this code in the constructor of your page object will allow the back navigation to take place only when the bound viewmodel is not busy:
Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
Command = new Command(async() =>
{
if (ViewModel.IsNotBusy)
{
await Shell.Current.Navigation.PopAsync();
}
})
});
In the body of the Command you can do whatever you need to do when you are intercepting the click of the back button.
Note that this will affect only the navigation back button, not the Android hardware back button - that will need handling separately as per the answers above. You could write a shared method called from both the back button pressed override and the command on shell back button behaviour places to share the logic.
You must override native navigationbar button behavior with custom renderer. OnBackButtonPressed triggers only physical device button. You can read good article how to achive this here

Xamarin Forms Ondisappearing() called soon after Onappearing()

Ondisappearing() called soon after Onappearing() and onAppearing called right after onDisappearing. I had this issue only on one page. other pages do not have this issue. I found this when I tap on navbar back button, it does not navigate to the previous page, I had to tap twice to navigate back on this particular page..then I found this problem. degraded forms version 4.0 to 3.5 and recreated new page did not solve this issue..help need...
public Cart_Page2 ()
{
InitializeComponent ();
}
protected override void OnAppearing()
{
base.OnAppearing();
var vm = new Cart_page_vm();
vm.Navigation = Navigation;
BindingContext = vm;
}
protected override void OnDisappearing()
{
// MessagingCenter.Send<Cart_page>(this, "cart_page_disappear");
// Navigation.PopAsync();
}

Alert in the view before navigation to other view through ondisaappeaing event

I have an android application in xamarin.forms with two view.While clicking on navigation back button in second view I need to show an alert the second view.
protected async override void OnDisappearing()
{
base.OnDisappearing();
if (_purchaseViewModel.ItemsCartList!=null && _purchaseViewModel.ItemsCartList.Count > 0)
{
var buyItems= await Helper.AskUserBuyOrDiscard("Information","Do you want to buy the selected items.");
if (buyItems)
{
_purchaseViewModel.DoneCommandHandler();
}
}
}
here the alert is appearing in first view.How can I dispaly the alert first and navigate to previous page next?

Button x:Name="btnBack" not navigating to previous page

I am developing Xamarin Forms application for IOS and Android.I have the list of 3 xamarin form pages say X.xaml, Y.xaml, Z.xaml. Page X.xaml, Y.xaml is having 1 and click on that button it opens the next-next Xamarin form. And last on Z.xaml having 2 buttons btnBack & btnConfirm
<Button x:Name="btnBack"></Button>
<Button x:Name="btnConfirm"></Button>
when I click on that back button I want to navigate it to my previous page, but I don't want it like Navigation Back Button or Hardware Back Button click.
for this I have tried this code this will not work.
Z.xaml.cs
public partial class Z : ContentPage
{
public Z()
{
InitializeComponent();
btnBack.Clicked += btnBack_Clicked;
}
private void btnBack_Clicked(object sender, EventArgs e)
{
var existingPages = Navigation.NavigationStack.ToList();
foreach (var page in existingPages)
{
if(page == this)
Navigation.RemovePage(page);
}
}
}
In this code when I click on Back Button it Navigate me to prevoius page ie Y.xaml once I click on button which is on Y.xaml and open the Z.xaml page it shows me blank.
Y.xaml.cs
public partial class Y: ContentPage
{
public Y()
{
InitializeComponent();
btnZ.Clicked += btnZ_Clicked;
}
void btnZ_Clicked(object sender, System.EventArgs e)
{
Navigation.PushAsync(new Z());
}
}
#Kowalski had the right answer however it is incomplete.
You have to await Navigation.PopAsync() otherwise you may mess up the navigation stack. So always await it. Example:
async void btnBack_Clicked(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
Beside that be aware that there are bugs in Xamarin.Forms related to navigation, here is one that might be interesting for you as well:
https://bugzilla.xamarin.com/show_bug.cgi?id=59172
P.S.: Here you can find the official guide on Popping Pages from the Navigation Stack.
you should invoke Navigation.PopAsync() to go back

Xamarin Forms: how not reload ListView when pop back

In Xamarin Forms i have a ListView and the following method in Code Behind:
protected async override void OnAppearing()
{
base.OnAppearing();
events.ItemsSource = await App.ServiceManager.GetStream();
}
where
events
is my ListView and fetch data from rest webservice.
When i select an item in the ListView i push a detail page. The problem is that when i pop back to the ListView, the method OnAppearing() is called and make the remote call again.
Instead i'd like that the scroll start from the previous position (before that i push a new page): how can do that?
I think you can simply use a
bool isFirstAppearing = true;
protected async override void OnAppearing()
{
base.OnAppearing();
if(isFirstAppearing) {
isFirstAppearing = false;
events.ItemsSource = await App.ServiceManager.GetStream();
}
}
You can either do a check if its already been loaded, as alessandro Caliaros answer suggests, or an alternative if you want to get fresh data but still be scrolled in the same position, you can add code in onappearing to set the scroll position to be the same as it was before:
var currentYPosition = _scrollView.ScrollY;
await _scrollView.ScrollToAsync(_scrollView.ScrollX, currentYPosition, true);

Resources