Pushing content page from background thread freezes app - xamarin

In Xamarin Forms for iOS, I have a custom renderer for a ContentPage that displays a video control. In my Xamarin Forms app, this custom ContentPage is displayed inside a NavigationPage.
I would like to have the video screen open when a specific message comes in via MQTT.
When I open the video page by clicking a link on the main screen, it opens as expected. I know I am receiving the message via MQTT and calling Navigation.PushModalAsync() because of console statements and breakpoints. However, the custom rendered page is not displayed and the UI of my app freezes each time after calling PushModalAsync.
Is there something else I need to do to trigger Navigation.PushModalAsync() based on receiving an MQTT notification in the background of my app?
ViewRoomsPage.axml.cs:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ViewRoomsPage : ContentPage
{
public ViewRoomsPage()
{
InitializeComponent();
}
public string StreamUri { get; set; }
}
ViewRoomsPage.axml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyForms.Pages.ViewRoomsPage">
<ContentPage.Content>
</ContentPage.Content>
VideoViewerRenderer.cs (video code removed; this should display a blank red screen. It also works when launched from a button on the main screen)
[assembly: ExportRenderer(typeof(ViewRoomsPage), typeof(ViewRoomsRenderer))]
namespace MyForms.IOS.NativeImplementations
{
public class ViewRoomsRenderer : PageRenderer
{
private IJKFFMoviePlayerController _playerController;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
e.NewElement.BackgroundColor = Color.Red;
}
}
}
Method triggered from receiving an MQTT message
public void PushViewRooms()
{
Device.BeginInvokeOnMainThread(async () =>
{
await Application.Current.MainPage.Navigation.PushModalAsync(new ViewRoomsPage());
});
}
In App.xaml.cs:
public partial class App : Application
{
public App()
{
SetupDependencies(); // using StructureMap
Manager = DependencyContainer.Resolve<IMqttManager>();
Manager.Connect();
InitializeComponent();
var mainPage = new MainPage();
MainPage = new NavigationPage(mainPage);
}
}

The problem was a deadlock caused by a Task.WaitAll() being triggered in another section of code running in the background.
Thanks all who helped sanity check that it wasn't something in the way the renderer was set up.

Related

How do I close all pages after changing an item's data?

I have a doubt in Xamarin forms, I have an application that I would like after finishing the training, it closes all the training screens and only the main screen remains, today I got a cod that does this, but when I restart the app and I login,
when he closes the screens instead of going back to the main screen he goes back to the login, I'm not using masterpage, could that be it?
source:
private async void BtnVoltar_Clicked(object sender, EventArgs e)
{
int numModals = Application.Current.MainPage.Navigation.ModalStack.Count;
// Pop each modal in the stack
for (int currModal = 0; currModal < numModals; currModal++)
{
await Application.Current.MainPage.Navigation.PopModalAsync();
}
await Navigation.PushModalAsync(new TabbedPageMenu());
}
Image Link
https://imgur.com/pOVVYBu
Another doubt would be after updating the data of an item, if it is possible to close the two screens and update it on the main screen
image link2
https://imgur.com/ZpevVNg
You can use the method to navigate to the different pages instead of close the pages.
The code in xaml you can add the command to do the navigation.
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type views:targetpagename}"
The code in xaml.cs or viewmodel
public ICommand NavigateCommand { get; private set; }
public MainPage()
{
InitializeComponent();
NavigateCommand = new Command<Type>(
async (Type pageType) =>
{
Page page = (Page)Activator.CreateInstance(pageType);
await Navigation.PushAsync(page);
});
BindingContext = this;
}

Xamarin Iconize IconTabbedPage Example

Can someone provide an example of how to use the IconTabbedPage in Iconize, preferably in Xaml? I have an IconTabbedPage with IconNavigation pages as children, all defined in Xaml. I then set the Icon property of the subpages by specifiying the font awesome name (“fa-home”). I tried to set the title as well, but neither of these will render the icon. I have search (a lot) for examples of the IconTabbedPage but couldn’t find any in Xaml. Additional bonus if you can provide an example of how to use the icons in a list cell context action.
Looking into #Niklas Code, you can create a tabbed page with a base class that inherits from IconTabbedPage , then your xaml will look like this.
<icon:IconTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:icon="clr-namespace:Plugin.Iconize;assembly=Plugin.Iconize"
....
>
<icon:IconTabbedPage.Children>
<ContentPage Title="Build" Icon="md-build">
</ContentPage>
</icon:IconTabbedPage.Children>
I hope it will help somebody
I think you can take a look on Sample on GitHub
[\[assembly: XamlCompilation(XamlCompilationOptions.Compile)\]
namespace Iconize.FormsSample
{
public class App : Application
{
public App()
{
// The root page of your application
var tabbedPage = new IconTabbedPage { Title = "Iconize" };
foreach (var module in Plugin.Iconize.Iconize.Modules)
{
tabbedPage.Children.Add(new Page1
{
BindingContext = new ModuleWrapper(module),
Icon = module.Keys.FirstOrDefault()
});
}
MainPage = new IconNavigationPage(tabbedPage);
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}][1]

What is the different between Navigation.PushModalAsync() andNavigation.PushAsync() In Xamarin Forms?

Reason for ask this i got error when i use PushAsync in xamarin forms mvvm architecture
await Navigation.PushAsync(new Page2());
Error is
I have corrected this error by changing PushAsync to PushModelAsync
await Navigation.PushModalAsync(new Page2());
anyone has idea about what cause to this error?
i am calling PushModelAsync from ViewModel
public class Page1Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public INavigation Navigation { get; set; }
public Command ContinueBtnClicked { get; }
public Page1Model(INavigation navigation)
{
this.Navigation = navigation;
this.ContinueBtnClicked = new Command(async () => await GotoPage2());
}
public async Task GotoPage2()
{
await Navigation.PushModalAsync(new Page2());
}
}
In your App.xaml.cs wrap your first page in a NavigationPage, like this: MainPage = new NavigationPage(new Page1());.
Now it will work. If you just have a single page, iOS doesn't know how to navigate to another page from there, so it needs a container page to handle navigation.
The reason the the modal variant works is because it spawns a new navigation stack and shows pages on top of everything else (hence modal).

reaching a page from xamarin.forms inside android project

I'm working on an android app with xamarin. I made tabbed pages. For the second page, i want to show the camerastream from my android camera. For that, some sample code said me I need to use a textureView inside the android part of the app, but that textureview needs to be putted on that second page. Whenever I try to reach a Stacklayout inside that Page, the following error shows up: 'Page1.camera' is inaccessible due to its protection level.
Using x:FieldModifier="public" inside that stacklayout doesn't work either.
Here is the structure of my code to make it more clear
Here I make the tabbed pages:
MainPage = new TabbedPage
{
Children = {
new MainPage(),
new Page1(),
new Page2()
}
};
Inside that Page1 i have this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App4.Page1"
Title="Licht">
<StackLayout x:Name="camera" x:FieldModifier="public" Orientation="Vertical">
</StackLayout>
</ContentPage>
And inside the MainActivity.cs i have this where i have to access the camera.
_textureView = new TextureView(Page1.camera);
And this is the structure of my app
And this is the structure of my app
Using x:FieldModifier="public" inside that stacklayout doesn't work either.
I have tried x:FieldModifier="public"in xamarin form, even though I use x:FieldModifier="public", the "camera" property is still private. This feature is not useful.
As far as I know there is no way to access "camera" inside MainActivity.cs in Xamarin form.
As a workaround you can design a page render for android platform and create a TextureView in your page render code.
how to create a page render
_textureView = new TextureView(Page1.camera);
BTW to initialize TextureView you need the object that implements the ISurfaceTextureListener interface at android platform.
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,ISurfaceTextureListener
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
TextureView textureView = new TextureView(this);
textureView.SurfaceTextureListener = this;
LoadApplication(new App());
}
public void OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
//start
}
public bool OnSurfaceTextureDestroyed(SurfaceTexture surface)
{
//stop
}
public void OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)
{
throw new NotImplementedException();
}
public void OnSurfaceTextureUpdated(SurfaceTexture surface)
{
throw new NotImplementedException();
}
}
Please follow the TextureView guide for Android.

Custom Popup in Xamarin.Forms

Is there any way to create custom popup dialog with Editor inside it using Xamarin Forms. Targeted to iOS platform.
I want a pop up with a Title Label ,Text box for accepting input and error Label for displaying error message, with OK and Cancel button.
I want to accept pin number from input pop up and have to validate pin. If validation fails I have to show a Error message inside pop up.
Thanks,
This is a good popup for XF that includes the ability to add an editor to the popup.
Popup Page Plugin for Xamarin Forms
// Use these methods in PopupNavigation globally or Navigation in your pages
// Open new PopupPage
Task PushAsync(PopupPage page, bool animate = true) // Navigation.PushPopupAsync
// Hide last PopupPage
Task PopAsync(bool animate = true) // Navigation.PopPopupAsync
// Hide all PopupPage with animations
Task PopAllAsync(bool animate = true) // Navigation.PopAllPopupAsync
// Remove one popup page in stack
Task RemovePageAsync(PopupPage page, bool animate = true) // Navigation.RemovePopupPageAsync
XAML POPUP PAGE
<?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"
x:Class="Demo.Pages.MyPopupPage">
<!--Animations use example-->
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="True"/>
</pages:PopupPage.Animation>
<!-- Content -->
</pages:PopupPage>
POPUP PAGE
public partial class MyPopupPage : PopupPage
{
public SecondPopupPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
}
// Method for animation child in PopupPage
// Invoced after custom animation end
protected virtual Task OnAppearingAnimationEnd()
{
return Content.FadeTo(0.5);
}
// Method for animation child in PopupPage
// Invoked before custom animation begin
protected virtual Task OnDisappearingAnimationBegin()
{
return Content.FadeTo(1);;
}
protected override bool OnBackButtonPressed()
{
// Prevent hide popup
//return base.OnBackButtonPressed();
return true;
}
// Invoced when background is clicked
protected override bool OnBackgroundClicked()
{
// Return default value - CloseWhenBackgroundIsClicked
return base.OnBackgroundClicked();
}
}
MAINPAGE
// Main Page
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
// Button Click
private async void OnOpenPupup(object sender, EventArgs e)
{
var page = new MyPopupPage();
await Navigation.PushPopupAsync(page);
// or
await PopupNavigation.PushAsync(page);
}
}
Have a look at ACR User Dialogs. https://github.com/aritchie/userdialogs
Nuget Package: https://www.nuget.org/packages/Acr.UserDialogs/
Then have a look at the Prompt Examples: https://github.com/aritchie/userdialogs/blob/master/src/Samples/Samples/ViewModels/StandardViewModel.cs#L97
void Prompt()
{
UserDialogs.Instance.ActionSheet(new ActionSheetConfig()
.SetTitle("Choose Type")
.Add("Default", () => this.PromptCommand(InputType.Default))
.Add("E-Mail", () => this.PromptCommand(InputType.Email))
.Add("Name", () => this.PromptCommand(InputType.Name))
.Add("Number", () => this.PromptCommand(InputType.Number))
.Add("Number with Decimal", () => this.PromptCommand(InputType.DecimalNumber))
.Add("Password", () => this.PromptCommand(InputType.Password))
.Add("Numeric Password (PIN)", () => this.PromptCommand(InputType.NumericPassword))
.Add("Phone", () => this.PromptCommand(InputType.Phone))
.Add("Url", () => this.PromptCommand(InputType.Url))
);
}
Yes, a custom popup can be added in Xamarin forms. Please follow these steps:
Create one stacklayout.
Add the fields in to the stacklayout.
Create one new Frame object.
Make the Frame object background with transaprent color.
Add the Stacklayout object into frame.
Add the frame to main content page.
If you need code, I will update.

Resources