Blank screen on debug of Xamarin app - visual-studio

I am not sure if it is just me, or everyone else out there, but every time i debug my Xamarin app on my mobile device i get a blank screen with an actionbar. The screen is displayed for about 2 seconds before it actually loads my specified screen.
Here is my PCL App.cs file:
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new LogInPage();
}
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
}
}
The blank screen:
and then finally, after a few seconds:

What you are seeing is the default theme of the Activity being shown while Xamarin Forms is being initialized. You will tend to see this during a cold start. One way to work around it is to add a Splash Screen to show during initialization (Xamarin Android Splash Screen doc).

Related

Xamarin iOS Splash Screen build from Windows Visual Studio

I'm trying to change my app's splash screen into a custom image, I haven't found a solution that solved it for me ... I will be more than happy if someone will be able to solve it.
Thanks
I'm using Xamarin iOS on Windows Visual Studio
You could consider adding a Page to your Forms project as a Splash Page.
like
public App()
{
InitializeComponent();
MainPage = new SplashPage();
}
Then add a delay in SplashPage to jump to MainPage.
public SplashPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
Task.Run(async ()=> {
await Task.Delay(3000);
Device.BeginInvokeOnMainThread(()=> { App.Current.MainPage = new MainPage();});
});
}

How can I set up my application main page (shell) from the OnAppearing of a login page with Xamarin Forms?

I have an application that I added a launch page to in the iOS and Android code. However when the app starts there is still quite a long delay while it fetches data. At this time there's a blank screen where I assume the app is still setting up the constructor.
I am trying to have an in-between page where that appears that loads the data. Not sure if this is the best way to do this but so far it's all that I have.
Here's the code that I have so far:
public App()
{
InitializeComponent;
MainPage = new NavigationPage(new Test.LoginPage())
{
};
}
My Test.LoginPage is a simple empty Xaml page with this C# back end:
public partial class LoginPage : ContentPage
{
public LoginPage()
{
InitializeComponent();
}
protected async override void OnAppearing()
{
await LongRunningTask();
App.MainPage = new AppShell(); // I want to start a shell app
}
}
public partial class AppShell : Shell
{
public AppShell()
{
Routing.RegisterRoute("HomeTab/QHPage", typeof(QHPage));
// etc
But the code has issues in that first of all I am not sure I am doing it correctly and secondly it says an object reference is required for App.MainPage.
Can anyone point me in the right direction and suggest how I could display this intermediate page and then display the real app pages?
Note that at some point I would also like to have a button on the login page that when clicked takes me to the app. But at this time I just want to get even the most simple version working so I am looking for some advice with that.
The easy way is to set the AppShell as MainPage. The code below works for me.
Application.Current.MainPage = new AppShell();

Override Fragment functions on Xamarin Android if fragment is created using Forms Embedding

I have created a forms page in Xamarin and used that page as a fragment using Xamarin Forms Embedding.
var fragment = new FormsPage().CreateFragment(context);
I would like to override the OnBackPressed() control in Android version of the app.
What's the best possible way to do it as I can't override it inside the Xamarin Forms Page.
I would like to override the OnBackPressed() control in Android version of the app.
You could override OnBackButtonPressed in Xamarin.Forms, this event also be raised when the hardware back button is pressed in Android and this event is not raised on iOS.
If you want remove fragment from the stack in OnBackPressed() method, you could override this method in your Activity like this :
public override void OnBackPressed()
{
base.OnBackPressed();
if (FragmentManager.BackStackEntryCount != 0)
{
FragmentManager.PopBackStack();
}
else
{
base.OnBackPressed();
}
}

Pushing content page from background thread freezes app

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.

Showing different toolbar buttons on each page with Xamarin Forms

I have 2 pages in my Xamarin Forms app. My first page has 4 icons in the toolbar. My second page is a login page and has a tick and a cross in the toolbar.
I can't get the login page to show any icons unless I make it a navigation page. I also have to clear ToolBarItems on the first page before calling PushAsync() otherwise it complains there are too many toolbar items.
If I call PopAsync() on the login page it does not return to the first page. I'm guessing this is due to their being 2 navigation pages. I also tried PopToRootAsync().The back button works however.
My question is - how do I show different toolbar icons on 2 different pages in a way that allows navigation to work?
I'm testing this on Windows Phone 8.0
Here is the code calling the login page:
private async void ShowLoginPage()
{
ToolbarItems.Clear();
var page = new NavigationPage(new LoginPage());
await Navigation.PushAsync(page);
}
and here is the code to return to the first page:
private void Cancel()
{
Navigation.PopToRootAsync();
}
I'm running Xamarin.Forms v1.2.2.6243
One thing you could try is to keep your Login Page inside of a NavigationPage, and then instead of running PopAsync() within the Login Page after they have logged in successfully, simply replace the MainPage with your old Navigation page:
In your App class:
public NavigationPage AppNavPage = new NavigationPage(new FirstPage());
public App() {
MainPage = AppNavPage;
}
In your FirstPage:
private async void ShowLoginPage() {
ToolbarItems.Clear();
var page = new NavigationPage(new LoginPage());
await Navigation.PushAsync(page);
}
In Login Page:
private async void OnCreateClicked(object sender, EventArgs e) {
bool loginInfoIsGood = CheckLoginInfo(); //Check their login info
if(loginInfoIsGood) {
Application.Current.MainPage = App.AppNavPage;
}
}
Otherwise, I have also done a custom renderer for the NavigationRenderer on iOS to insert toolbar items onto the right side of the Navigation Bar and have overridden some Menu related stuff on Android to change the icon text/colors.
One option that you have, and one that I implemented in my own app, is a custom renderer that removes the navigation header from the app and then you could build your own custom header. With this approach, you do lose some of the native feel of the app, and you have to implement much of the transitional functionality your self. However, it gives you alot more control over the look.
CustomRenderer that removes the navigationBar:
//add using statements
// add all view here that need this custom header, might be able to build a
//base page that others inherit from, so that this will work on all pages.
[assembly: ExportRenderer(typeof(yourView), typeof(HeaderRenderer))]
class HeaderRenderer : PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
this.NavigationController.SetNavigationBarHidden(true, true);
}
}
After this you can build a header view that can be placed on the top of every page (I am using xaml) so I don't know if it is relevant in you application.
Edit: You might need to change this renderer for differnt page types.

Resources