I have a project using MAUI Hybrid to produce an Android Application (apk).
A blazorWebView is running in MAUI app, so that the code of pages is used by both Web Site (un Blazor Wasm) and MAUI app (MAUI + Blazor WebView).
A blazorWebView is included in MAUI App (code from MainPage.xaml) :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui"
xmlns:local="clr-namespace:MyMauiBlazor"
x:Class="MyMauiBlazor.MainPage">
<b:BlazorWebView HostPage="wwwroot/index.html">
<b:BlazorWebView.RootComponents>
<b:RootComponent Selector="app" ComponentType="{x:Type local:Main}" />
</b:BlazorWebView.RootComponents>
</b:BlazorWebView>
</ContentPage>
On Android devices, is it possible to handle the Back Button pressed ?
Currently, the App closes, but I want to handle this event (ex : navigate to previous page).
Is there a way to do this ?
I had the same problem as you, officially microsoft doesn't support back key navigation for MAUI blazor yet, but I found a temporary solution for that:
First you have to create a javascript file, and put it in the wwwroot folder, and include it in the index.html file. Inside the js file put this code:
window.goBack = () => {
history.go(-1);
}
Then you have to create a c# class and make it a service, so for example I created a class called GoBack.cs. To set it as a service just put this code in MauiProgram.cs:
builder.Services.AddTransient<GoBack>();
In the GoBack class you have to create a static variable and method, because otherwise you will not be able to use the IJSRuntime interop. My GoBack file is the following:
public class GoBack
{
private static IJSRuntime JSRuntime { get; set; }
public GoBack(IJSRuntime jSRuntime)
{
GoBack.JSRuntime = jSRuntime;
}
public static async Task GoBackInTime()
{
//Microsoft.Maui.Platform;
if (GoBack.JSRuntime != null)
{
await GoBack.JSRuntime.InvokeVoidAsync("goBack");
}
}
}
The method GoBackInTime is going to call the js method goBack through the jsInteroperability. Now you have to inject in the first blazor page that you load this service.
#inject GoBack goBack
This way the jsRuntime in the cs file will be initialized and not null.
Now all you have to do is override the OnBackButtonPressed method in MainPage.xaml.cs:
protected override bool OnBackButtonPressed()
{
GoBack.GoBackInTime();
return true;
}
This way, when the back button is pressed, it won't exit the application (because we are returning true) and at the same time the js function is called so the blazor page will navigate to the previous page.
Related
I'm using Xamarin Forms using a WebView to display content. To send commands from the webpage to the app, I'm using links with URLs like this:
myapp://command=123&someparam=456
this is then handled in the PCL project like this:
private async void CustomWebView_Navigating(object sender, WebNavigatingEventArgs e) {
if (e.Url.Contains("myapp://")) {
e.Cancel = true;
// Some app logic
}
...
This all worked well up until recently when Android phones began displaying an error page saying:
Webpage not available
ERR_Unknown_URL_Scheme
CustomWebView_Navigating is still being triggered, but how can I prevent the error page from showing?
Note: I have tried overriding ShouldOverrideUrlLoading and returning 'true' - but then CustomWebView_Navigating is no longer triggering in the PCL project.
I am a newbie in xamarin forms app development, currently, I am facing an issue in overriding the toolbar back button onclick. In ios, I am able to achieve but in android its not working can anyone help me out on how to achieve this in my project.
By default it works on iOS and on Android physical back button only. If you want to also support the navigation bar button, you need to use custom platform logic. Take a look on this blog post: Let’s Override Navigation Bar back button click in Xamarin For. He creates a common content page with custom action for back button:
public class CoolContentPage : ContentPage
{
/// <summary>
/// Gets or Sets the Back button click overriden custom action
/// </summary>
public Action CustomBackButtonAction { get; set; }
public static readonly BindableProperty EnableBackButtonOverrideProperty =
BindableProperty.Create(
nameof(EnableBackButtonOverride),
typeof(bool),
typeof(CoolContentPage),
false);
/// <summary>
/// Gets or Sets Custom Back button overriding state
/// </summary>
public bool EnableBackButtonOverride
{
get
{
return (bool)GetValue(EnableBackButtonOverrideProperty);
}
set
{
SetValue(EnableBackButtonOverrideProperty, value);
}
}
}
And then he calls CustomBackAction inside OnOptionsItemSelected method in Anroid code.
Best way to intercept Back Navigation ( Navigation in general ) would be by adding your NavigationPageRenderer so you can control the events and cancel or redirect them, look at my answer How to intercept Navigation Bar Back Button Clicked in Xamarin Forms?
I came to this post with same question about Xamarin forms navigation back button and later discovered that since Xamarin.Forms Shell this is done easily by overriding the OnNavigating method in the AppShell.xaml.cs file as I have done here:
protected override void OnNavigating(ShellNavigatingEventArgs e)
{
// Make sure it's safe to examine the current page
if ((Shell.Current != null) &&
(Shell.Current.CurrentPage != null))
{
Console.WriteLine($"{e.Source} {Shell.Current.Title}");
if (
// Detect Back Navigation
e.Source == ShellNavigationSource.Pop &&
// Cancel or Not, based on (for example) the Title of the current page.
(Shell.Current.Title != "My Main Page"))
{
e.Cancel();
Shell.Current.GoToAsync("..");
}
}
base.OnNavigating(e);
}
In case anyone else stumbles upon, I put a sample on GitHub of what worked for me for Android and iOS both.
Is there any library which has ability like moveTaskToBack in React Native?
Previously I use https://github.com/jaysoo/react-native-activity-android and it has moveTaskToBack. But unfortunately this repo is not active anymore, and since React Native 0.29, it has some internal change which make that library didn't work.
I'm not sure it's what you need, but if you put this in your MainActivity.java class:
#Override
public void invokeDefaultOnBackPressed() {
// do not call super.invokeDefaultOnBackPressed() as it will close the app. Instead lets just put it in the background.
moveTaskToBack(true);
}
Then when user press the android back button on the "root" page, the app will go in background instead of being closed.
Source: background a react-native android app using back button
Use react-native-navigation, then navigate to your projects node modules folder and locate the react-native-navigation folder and inside it, follow the path to the NavigationActivity.java:
/android/app/src/main/java/com/reactnativenavigation/controllers/NavigationActivity.java.
In the NavigationActivity.java file, you will see the following method at around line 196:
#Override
public void invokeDefaultOnBackPressed() {
if (layout != null && !layout.onBackPressed()) {
super.onBackPressed();
}
}
Comment out the line: super.onBackPressed() and add the line: this.moveTaskToBack(true);
and thats all! Happy coding
How can i use the Navigation Page for Android in Xamarin Form ?
I use this but it didn't work:
I want, when i press my button, to switch to my secondPage (DemoPage)
I don't know how i can do this.
Thank you
simply wrap your "main" page in a NavigationPage when you assign it in your App's constructor
public class App : Application
{
public App ()
{
// The root page of your application
MainPage = new NavigationPage(new MyMainPage());
}
}
i've tried in every way to call the requestWindowFeature method, first inside a page script (but raised a very nice error), second on app js, working inside application.launchEvent closure:
var application = require("application");
application.mainModule = "main-page";
application.cssFile = "./app.css";
application.on(application.launchEvent, function (args) {
if (args.android) {
// How to work with android activity in this closure?
}
});
application.start();
I was not able to get an android activity instance in order to hide the default title bar.
Assuming that the "launchEvent" event it is assimilable to "onCreate" event, is there a way to get the android activity in this context? Or is necessary to assume that it isn't the proper way in order to achieve the goal?
For the time being you can try this:
application.on(application.launchEvent, function (args) {
if (application.android) {
var activity = application.android.startActivity;
// Do something with activity...
}
});
Our next release will include Android Activity Events. Here is the pull request.