Save & Restore Page in Xamarin Forms - xamarin.forms

I'm looking to save the current navigation stack on the OnSleep Event in my Xamarin Forms page and restore it on the OnResume Event. Is it possible to do this?
Cheers!

I think you should not memorize all navigation stack. Your device decide to kill your app or to restart from the last page you have seen when it comes up from background. I think you can memorize if you are "Logged in" or not: if you are "Logged in" you can restart from the first page "after the login", otherwise start "from the login".
For this case you can take a look to this link and use Properties
public class App : Xamarin.Forms.Application
{
public App ()
{
}
protected override void OnStart()
{
// Handle when your app starts
Debug.WriteLine ("OnStart");
checkLogin();
}
protected override void OnSleep()
{
// Handle when your app sleeps
Debug.WriteLine ("OnSleep");
}
protected override void OnResume()
{
// Handle when your app resumes
Debug.WriteLine ("OnResume");
checkLogin();
}
}
void checkLogin(){
if (Application.Current.Properties.ContainsKey("IsLogged"))
{
var IsLogged = Application.Current.Properties ["IsLogged"] as bool;
// do something with IsLogged
if(IsLogged)
MainPage = new MyFirstPage();
else
MainPage = new MyLoginPage();
}
else
MainPage = new MyLoginPage();
}
then, when you have logged in
Application.Current.Properties ["IsLogged"] = true;

Related

Xamarin.Forms MvvM Prism Software and Hardware Back Button

I have problem with implementation Code which resolve problem with confirm software nad hardware button back. I need confirm and save state page field. When confirm is true and save state have no error I want close page and when confirm is false or save state have error I want stop closing page. I use xamarin.forms with mvvm prism.
If you mean want to custom the method of Software and Hardware Back Button of Android device, you could override OnOptionsItemSelected and OnKeyDown method in MainActivity.cs to achieve that.
Software Back Button code in MainActivity.cs:
protected override void OnCreate(Bundle savedInstanceState)
{
...
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
SupportActionBar.SetHomeButtonEnabled(true);
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
if(item.ItemId == Android.Resource.Id.Home)
{
Console.WriteLine("software back button press");
return false;
}
else
{
return base.OnOptionsItemSelected(item);
}
}
Hardware Back Button code in MainActivity.cs:
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
{
if(e.Action == KeyEventActions.Down && keyCode == Keycode.Back)
{
Console.WriteLine("hardware back button press");
}
return false;
}

Xamarin.Forms how to change the Theme based on time of the day

I have scenario like this: Have two themes Light and Dark . I have a binding from the viewmodel what theme to add. I just don't know how to get time from device and organize . I need after 7 PM everyday the theme change to Dark , its Light by default. How to organize this?
I Suggest that you create an property in the App.xaml.cs, in the app Start/Resume methods, verify the hour of the day, and then on your ViewModel you will have access to this value.
App.xaml.cs:
public bool IsDarkTheme;
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
public void SetTheme()
{
TimeSpan day = DateTime.Now.TimeOfDay;
if (!(day.Hours < 19 && day.Hours > 6))
{
IsDarkTheme = true;
}
}
protected override void OnStart()
{
// Handle when your app starts
SetTheme();
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
SetTheme();
}
Note: if the user opened the app before 7pm and resumes it after, and you want the page that was resumed to change apearence, you will need to add this to the pages (if you do this, you no longer need to define the value in the ViewModel constructor):
On the Pages xaml.cs:
protected override void OnAppearing()
{
((TheViewModelAssociated)BindingContext).TheViewModelProperty = App.IsDarkTheme;
base.OnAppearing();
}
Your ViewModel you access it like this:
App.IsDarkTheme

Handling Keyboard Input at the Page Level with Xamarin Forms

I am working on a Xamarin Forms project for which one requirement is to recognize certain key presses to trigger hot key actions. The devices that we will be deploying the application to have physical keyboards attached. For now, Android is the only platform that is being targeted.
From some research that I did yesterday afternoon, it sounds as though a custom page renderer is what is required. As I played with this concept this morning, I stumbled upon the On* key methods of the Activity class.
I tried adding the following to the MainActivity class in the Android project:
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
{
return base.OnKeyUp(keyCode, e);
}
Placing a breakpoint on this method seems to show that this code is what is needed (read, this method is fired whenever I press a key on the keyboard).
The issue is that this method is also fired when an Entry control on the page has focus. Shouldn't the key press be handled by the Entry control and not bubbled up to the page?
Generally speaking, is this the right approach for what I am trying to accomplish? Are there other approaches that someone can point me to that might work better?
When I was working with hardware devices, I had to do something similar. I created a custom renderer for an entry on the Xamarin.android side. This captures the Enter key press for both hard and soft key in different events. I think creating custom render for a page like you did could work too but this only captures key presses for elements that are in focus. This works for me as I have the entry in focus when user presses the hardware Enter key.
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace Project.Droid.Controls {
public class CustomEntryRenderer : EntryRenderer {
public CustomEntryRenderer(Context context) : base(context) {
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) {
base.OnElementChanged(e);
Control.EditorAction += Control_EditorAction;
Control.KeyPress += NativeEditText_KeyPress;
}
// Fires only for Soft Keyboard
private void Control_EditorAction(object sender, Android.Widget.TextView.EditorActionEventArgs e) {
if (e.ActionId == ImeAction.Done) {
// your code
e.Handled = true;
}
}
// Fires for Hard Keyboard
private void NativeEditText_KeyPress(object sender, KeyEventArgs e) {
if (e.KeyCode == Keycode.Enter && e.Event.Action == KeyEventActions.Up) {
// your code
e.Handled = true;
}
else
e.Handled = false;
}
}
}
FYI: I also tried the MainActivity event that you are using and it did not work for me. I cannot recall why.

How to Handle Back Button in Persistent Search Library

In my App i am Using Navigation Drawer and Persistent Search Library in Action
bar https://github.com/KieronQuinn/PersistentSearch
So when i am in my Home Activity and Search View is not Shown and i press back Button
App is Exit Normally (No Issue)
But when Search View is Open and i Press back button there is an Exception Occurs
So i want to know how to handle Back Button In Persistent Search Library
Here is the Exception Details
Exception image
I figure out the way of handling this as
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (this.search.isActivated()) {
closeSearch();
}
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
But Same Exception Occures
Any help will be Appreciated
Put this code in your activity to handle backpress event for search view
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getKeyCode() == 4 && binding.appBrLt.searchbox.getVisibility() == View.VISIBLE) {
//here write the code
return true;
} else {
return super.dispatchKeyEvent(e);
}
}

Navigating from Platform Specific (UWP) PageRenderer and back to PCL Page

I have a MainPage in PCL which then navigates to a Platform Specific
Login Page on LoginButton Click Event
The LoginPage is inherited from
platform specific PageRenderer as it needs platform specific
Authentication to Social Providers (Facebook, Google, Twitter,
Microsoft, etc.)
I am using Xamarin.Auth to do the authentication.
Inside the OnElementChanged event of the LoginPage, it instantiates
the OAuth2Authenticator object.
Upon successful instantiation (based
on provider and app details), it needs to call the UI of the specific
provider.
To do that, I call the auth.GetUI where auth is
Xamarin.Auth.OAuth2Authenticator object.
I have two questions:
In UWP, how do I navigate to the provider login UI? More specifically, what is the equivalent in UWP of the following code snippets in iOS and Android? In iOS, the following code is used:
PresentViewController(auth.GetUI(), true, null);
where auth is Xamarin.Auth.OAuth2Authenticator object.
In Android the following is used:
activity.StartActivity(auth.GetUI(activity));
I am looking for the equivalent code in UWP. Please bear in mind that these calls are made from the LoginPage which is derived from Platform specific PageRenderer
How do I navigate back to my MainPage (which is in PCL) upon successful authentication?
The code is based off of a sample from the following source:
http://www.c-sharpcorner.com/article/oauth-login-authenticating-with-identity-provider-in-xamarin-forms/
Here is my code for the LoginPage:
using System;
using Valufy;
using Xamarin.Forms.Platform.UWP;
using System.ComponentModel;
using Valufy.UWP;
using Valufy.AuthConfiguration;
using Xamarin.Forms;
[assembly: ExportRenderer(typeof(ProviderLoginPage), typeof(LoginRenderer))]
namespace Valufy.UWP
{
class LoginRenderer: PageRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
//Get and Assign ProviderName from ProviderLoginPage
ProviderLoginPage loginPage = (ProviderLoginPage)Element;
string providername = loginPage.ProviderName;
//Create OauthProviderSetting class with Oauth Implementation .Refer Step 6
OAuthProviderSetting oauth = new OAuthProviderSetting();
Xamarin.Auth.OAuth2Authenticator auth = oauth.LoginWithProvider(providername);
// After facebook,google and all identity provider login completed
auth.Completed += Auth_Completed;
Type page_type = auth.GetUI();
//////THIS IS WHERE I AM STUCK...HOW DO I GO TO THE PROVIDER AUTH UI ////////////
//this.Frame.Navigate(page_type, auth);
//parentPage.Navigation.PushModalAsync(auth.GetUI());
}
}
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
OAuthConfig.User = new UserDetails();
// Get and Save User Details
OAuthConfig.User.Token = e.Account.Properties["oauth_token"];
OAuthConfig.User.TokenSecret = e.Account.Properties["oauth_token_secret"];
OAuthConfig.User.TwitterId = e.Account.Properties["user_id"];
OAuthConfig.User.ScreenName = e.Account.Properties["screen_name"];
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
else
{
// The user cancelled
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
}
}
}
Here is the code to navigate to the provider login for UWP:
WindowsPage windowsPage = new WindowsPage();
_frame = windowsPage.Frame;
if (_frame == null)
{
_frame = new Windows.UI.Xaml.Controls.Frame
{
Language = global::Windows.Globalization.ApplicationLanguages.Languages[0]
};
windowsPage.Content = _frame;
SetNativeControl(windowsPage);
}
Type pageType = auth.GetUI();
_frame.Navigate(pageType, auth);
To navigate back to my page upon successful authentication, here is the code:
private async void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
var request = new OAuth2Request("GET", new Uri("https://login.microsoftonline.com/common/oauth2/V2.0/token?oauth2_access_token=" + e.Account.Properties["access_token"]), null, e.Account);
try
{
string response = await MSGetUserInfo(e.Account);
}
catch (System.OperationCanceledException)
{
}
catch (Exception ex)
{
}
this.Element.Navigation.PushModalAsync(new MainPage());
}
else
{
// The user cancelled
}
}
1- In UWP, how do I navigate to the provider login UI
You need to create a UWP Page object, the same object you are will use to display in the renderer is the one you will use to do the navigation.
Type page_type = auth.GetUI();
page = new MyUWPLoginPage();
page.Frame.Navigate(page_type, auth);
2- How do I navigate back to my MainPage (which is in PCL) upon successful authentication?
There are many ways to do this, the easiest one is creating a public method in your ProviderLoginPage class and from the renderer classes call this method and pass-in the parameters.
public class ProviderLoginPage: ContentPage
{
......
public void AuthenticationCompleted(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
// Do your logic
}
}
In your Renderer using the Element:
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
var xamElement = Element as ProviderLogin;
xamElement?.AuthenticationCompleted(sender, e);
}
Move all the logic to the PCL class so you don't have to repeat it on each renderer.
This should help.

Resources