Xamarin PCL splash screen containing a web service call - xamarin

I'd like to have a Xamarin PCL ContentPage that displays a welcome message and then loads data from a web service. I have the web service working but the problem is that in the following example nothing is displayed while it takes time to work.
What is the general strategy for: displaying a wait-type Splash page, waiting for a long-running task to complete, and then continuing with the rest of the application (say a Main Menu page)?
Hopefully the strategy will work in the PCL project so that I don't have to try and write iOS and Android versions? I've tried to put code in various override methods, but nothing seems to work. Thanks in advance for any advice.
// The following is called from the "App : Application" class.
public class SplashScreen : ContentPage
{
public SplashScreen()
{
Label lblWelcome = new Label { Text = "Hello. Please wait..." };
Content = new StackLayout
{
Children = { lblWelcome }
}
//TODO: Have the device display the above content before the following continues...
CallWebServiceToLoadParameters();
//TODO: Move on to display the Main Menu
}
}

This may do the trick:
public class SplashScreen : ContentPage
{
public SplashScreen()
{
Label lblWelcome = new Label { Text = "Hello. Please wait..." };
Content = new StackLayout
{
Children = { lblWelcome }
}
Device.BeginInvokeOnMainThread(async () => {
//If awaitable
var response = await CallWebServiceToLoadParameters();
if(response{
App.Current.MainPage = //Your main page.
}
});
}
}
A little bit ugly, the correct way will be with a ViewModel for each page.

Related

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();

Xamarin Forms iOS TitleBarTextColor not changing

To change the TitleBarTextColor so far I tried a lot and my code now does change the back button color and the area on the very top of the screen, but the title!
in my AppDelegate FinishedLaunching function (it's after Forms.Init() and before LoadApplication()):
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes
{
TextColor = UIColor.White
});
In my ViewModel:
(App.Current.MainPage as NavigationPage).BarBackgroundColor = Color.FromHex("#990000");
(App.Current.MainPage as NavigationPage).BarTextColor = Color.White;
And this is how I'm navigating between the pages (not all the pages):
await _navigationService.NavigateAsync(new Uri("http://wwww.x.com/NavigationPage/TabbedNavigationPage?selectedTab=XPage/Document", UriKind.Absolute));
I even try to call the ViewModel code after the Prism navigation but it doesn't work... I'm a beginner and don't fully comprehend Prism and or Xamarin Forms.
[EDIT] -> I also tried to create a new class and inherit it from NavigationPage, set the BarTextColor in its constructor and use that class in the navigation like this: await _navigationService.NavigateAsync(new Uri("http://wwww.x.com/NEWCLASSCREATED/TabbedNavigationPage?selectedTab=XPage/Document", UriKind.Absolute)); But, as you may know, it is still not working.
Here's a Image ;)
imageToSeeThatImNotLying
Thank you for your support!
So I finnaly managed to work this out...
What I had to do was to create a custom Content Page because all the other solutions wasn't working. So I created this custom renderer only in my iOS project:
[assembly: ExportRenderer(typeof(ContentPage), typeof(CustomContentPageRenderer))]
namespace TestProject.iOS.Bll.Utils.Renderers
{
public class CustomContentPageRenderer : PageRenderer
{
public override void DidMoveToParentViewController(UIViewController parent)
{
base.WillMoveToParentViewController(parent);
var titleView = new UITextView();
var page = this.Element as ContentPage;
try
{
if (!string.IsNullOrEmpty(page.Title))
{
titleView.Text = page.Title;
titleView.TextColor = UIColor.White;
titleView.Font = UIFont.SystemFontOfSize(17, UIFontWeight.Regular);
var bgColor = page.BackgroundColor;
titleView.BackgroundColor = UIColor.FromRGBA((int)bgColor.R, (int)bgColor.G, (int)bgColor.B, 0);
parent.NavigationItem.TitleView = titleView;
parent.NavigationItem.TitleView.ContentMode = UIViewContentMode.ScaleAspectFit;
}
}
catch (Exception e)
{
}
}
}
}
And I also removed all the code that I puted before in my AppDelegate file and in the App.xaml.cs file as well. I left the codes from the ViewModels because it was changing the back button to white, and I deleted the new NagivationPage class that I created before.
I'm going to explain why I did some of the things that you saw there:
To change the Title I created a UITextView() and set it to my NavigationItem.TitleView of the parent page. I set titleView.Text = page.Title; because my original page already have a title, so I'm just reusing it. And the backgroundcolor I had to do all of that so the backgroundcolor property works just in the way that I wanted.
And this DidMoveToParentViewController function was just so it can do all that before NavigationAsync from Prism.

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]

ARCGis Xamarin - MapView from previous page displays after navigating to new page

I have a 'main' map page from which the user can either add data to the map or click on existing data to see the details. This is done with PushModalAsync() where I navigate to a new page. My problem is in both of those new pages I have a new map with a new MapView that is 'underneath' the MapView from the 'main' page. Both the MapView and Map itself are new objects on the secondary pages.
After navigating to my new pages, the previous MapView shows in the area of the screen where it existed (on 'main' page) where my new MapView also exists. In other words, on my new map pages my map is laid out differently and partially sits higher in the layout than the 'main' map does. The part that sits higher is the only part of the new map that is visible and I can interact with. The part that sits on the same area is the 'main' map view and I cannot interact with it and it blocks my new map.
I tried this with PushAsync as well (not modal) and nothing changed. How is one supposed to have multiple maps in an app across multiple pages? Is this even possible with ArcGIS? This app used to be with Google Maps/Apple and the exact same layout worked just fine.
Edit: Code here (with irrelevant parts removed) This page is navigated to from another page with a map on it wherein this map is covered if it is laid out in the same area of the first map. From this page I navigate to a 3rd page where both maps show up. Removal works successfully, however when I try to add I get an error saying I cannot add a null child to a view group:
public partial class EventDetails : ContentPage
{
public Xamarin.Forms.Grid MapGrid = new Xamarin.Forms.Grid()
{
RowDefinitions =
{
new RowDefinition { Height = 220 },
new RowDefinition { Height = GridLength.Auto }
},
ColumnDefinitions =
{
new ColumnDefinition { Width = 500 }
},
HorizontalOptions = LayoutOptions.Center
};
public Map DetailMap;
public MapView MyDetailMapView = new MapView();
public EventDetails(MapLog eventDetails, string strMapType)
{
DetailMap = new Map(BasemapType.ImageryWithLabels, eventDetails.Latitude, eventDetails.Longitude, iMapDetail);
MyDetailMapView.Map = DetailMap;
MyDetailMapView.ViewpointChanged += MyMapView_ViewpointChanged;
var scrollView = new ScrollView
{
Content = mainStack
};
MapGrid.Children.Add(MyDetailMapView, 0, 0);
MapGrid.Children.Add(scrollView, 0, 1);
Content = MapGrid;
}
#if __ANDROID__
protected override void OnAppearing()
{
if (!MapGrid.Children.Contains(MyDetailMapView))
{
try
{
MapGrid.Children.Add(MyDetailMapView);
}
catch (Exception ex)
{
DisplayAlert("Err", ex.Message, "Ok");
}
}
base.OnAppearing();
}
protected override void OnDisappearing()
{
if (MapGrid.Children.Contains(MyDetailMapView))
MapGrid.Children.Remove(MyDetailMapView);
base.OnDisappearing();
}
#endif
}
EDIT*: I updated my Xamarin Forms version and ARCGIS Runtime and now the solution to remove/add the map does work without issue.
I had other similar problems with having two maps for android in Xamarin Forms ArcGIS and the solution was removing the MapView from the visual tree when you navigate to the new page.
You need to remove the MapView before you Navigate to the second page by:
[your parent layout].Children.Remove(MyMapView);
await Navigation.PushAsync(new SecondPage());
And in your first page you need to make sure to add the MapView back to the Visual Tree when you come back to the page:
protected override void OnAppearing()
{
if (!GridMap.Children.Contains(MyMapView))
GridMap.Children.Add(MyMapView);
base.OnAppearing();
}
That solved all my problems with two maps. Thanks to this post in ESRI forum
Navigation between 2 MapViews in Xamarin Android

How do you switch between two different Xamarin Form pages?

I'm trying to figure out how to switch between two different pages in Xamarin Forms.
I do not wish to use a NavigationPage (which has that little back arrow that is auto displayed.
I have a Login page (which is a ContentPage) and once the person has authenticated, I then need to navigate to my Dashboard page (which is a TabbedPage).
eg.
Next, one of the Tab's in the TabbedPage is the profile of the logged in user. As such, I need to log them out. So i'll have a button to log them out, which means I will need to navigate them back to the Login page (which was that ContentPage).
I feel like I have two modes the user might be in.
UnAuthorized. (ContentPage)
Authorized. (TabbedPage).
It's like I need to change the App's MainPage to be either one of those two?
To change MainPage to another just do:
App.Current.MainPage = new NavigationPage(new MyContentPage());
or
App.Current.MainPage = new MyContentPage();
BTW: You can use a NavigationPage and then HIDE the toolbar with:
NavigationPage.SetHasNavigationBar(this, false);
You can do navigation as usual by setting MainPage in your Application instance. Small sample.
namespace TestNavigation
{
public class App : Application
{
public App ()
{
// The root page of your application
MainPage = new MyPage1 ();
}
}
}
namespace TestNavigation
{
public class MyPage1 : ContentPage
{
public MyPage1 ()
{
var button = new Button () {
Text = "Click me"
};
button.Clicked += (object sender, EventArgs e) => {
Application.Current.MainPage = new MyPage2 ();
};
Content = new StackLayout {
Children = {
button
}
};
}
}
}
namespace TestNavigation
{
public class MyPage2 : ContentPage
{
public MyPage2 ()
{
Content = new StackLayout {
Children = {
new Label { Text = "Hello ContentPage" }
}
};
}
}
}
EDIT1
I submitted this answer but then I realised that I probably don't understand your problem.
EDIT2
Updated sample.
If you like to switch between the pages then you can simply do
Application.Current.MainPage=new YourPage();
How to Change MainPage in xamarin forms at runtime?
this is what i have done to get result
For a login page, the best practice is to use
await Navigation.PushModalAsync (new LoginPage());
Once you are on the LoginPage, you can use popModelAsync after the validation is passed:
await Navigation.PopModalAsync ();

Resources