I'm building a Xamarin.Forms application with a facebook login using Xamarin.Auth.
Entry point (app.cs):
public App()
{
MainPage = new WelcomePage();
}
WelcomePage:
using System;
using Xamarin.Forms;
namespace Project
{
public class WelcomePage : ContentPage
{
public WelcomePage()
{
var login = new Button { Text = "Login" };
login.Clicked += (sender, e) =>
{
Navigation.PushModalAsync(new LoginPage());
};
Content = new StackLayout
{
BackgroundColor = Color.FromHex("F0C640"),
Padding = new Thickness(10, 40, 10, 10),
Children = {
new Label { Text = "Please login" },
login
}
};
}
}
}
LoginPage:
using Xamarin.Forms;
namespace Project
{
public class LoginPage : ContentPage
{
}
}
This is empty as I use Xamarin.Auth to authenticate with facebook so I created 2 different renderers on iOS and Android to display the facebook login page. After the login success I call an action which is located in my app.cs file:
public Action SuccessfulLoginAction
{
get
{
return new Action(() => goToMainPage());
}
}
public void goToMainPage()
{
MainPage.Navigation.PopModalAsync();
//MainPage.Navigation.PopToRootAsync();
MainPage.Navigation.PushAsync(new DetailPage());
}
At the end of the authentication the page is white but I believe it's a white page from Facebook after the authentication is done.
The SuccessfulLoginAction is well called so I go through the goToMainPage() function.
I put some breakpoints and PopModalAsync() doesn't do anything, same for PopToRootAsync() and PushAsync()...
The DetailPage is just a page with a Label. If I try to display it at the beginning of the process (app(){}) it display it well.
Thanks.
Related
I would like to create an application with a navigation drawer. So each page should be accessible via drawer "link" item.
To protect those pages the application should only be accessible on a valid session otherwise the login page should be rendered.
I'm trying to explain what I've done so far for reproduction purposes...
After creating a new Xamarin forms project I created a MainPage holding the drawer and the currently rendered page
public class MainPage : MasterDetailPage
{
public MainPage()
{
Master = new MasterPage();
Detail = new NavigationPage(new DummyPage()); // Set initial page
}
}
So the MasterPage (drawer) is empty for now
internal class MasterPage : ContentPage
{
public MasterPage()
{
Title = "Master";
Content = new StackLayout { Children = { } };
}
}
Same for the rendered DummyPage
class DummyPage : ContentPage
{
public DummyPage()
{
Title = "Dummy";
Content = new StackLayout { Children = { new Label { Text = "Dummy Page" } } };
}
}
So without a LoginPage my App file would look like
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
}
The rendered application then looks fine
When I try to render a LoginPage before accessing the main application part I would do something like
public partial class App : Application
{
public App()
{
InitializeComponent();
Page initialPage;
if (false) // check if logged in
{
initialPage = new LoginPage();
}
else
{
initialPage = new MainPage();
}
MainPage = new NavigationPage(initialPage);
}
}
Unfortunately the rendered MainPage then looks like
How can I fix that? What is missing or wrong?
Update
I found out that I can set the current displayed page globally. So for the start I do
public App()
{
InitializeComponent();
Page initialPage;
if (isLoggedIn)
{
initialPage = new LoginPage();
}
else
{
initialPage = new MainPage();
}
MainPage = initialPage;
}
and when clicking the "Sign In" button on the LoginPage I don't execute
SignInCommand = new Command(() =>
{
await Application.Current.MainPage.Navigation.PushAsync(new MainPage());
});
This works for me
SignInCommand = new Command(() =>
{
Application.Current.MainPage = new MainPage();
});
You should try this
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage(false);
}
}
public class MainPage : MasterDetailPage
{
public MainPage(bool value)
{
Master = new MasterPage();
Detail = value ? new NavigationPage(new LoginPage()) : new NavigationPage(new DummyPage());
}
}
I think navigation doesn't add the main container.
It seems that you put the MasterDetailPage in a NavigationPage . Actually , it is nappropriate to do it . You could improve the code like following
public partial class App : Application
{
public App()
{
InitializeComponent();
if (false) // check if logged in
{
MainPage = new NavigationPage(initialPage);
}
else
{
MainPage = new MainPage();
}
}
}
I'm really trying to work my way through a Xamarian.Form app an I'm finding it difficult because the template out of the box doesn't seem to work.
Basically on the menu I'm trying to nav to the Browse or About page.
however MainPage RootPage { get => Application.Current.MainPage as MainPage; } is returning null.
I've made no changes to this template but I do understand C# so I roughly understand the issue but I'm not aware as to why this is returning null, certainly from the starting template.
MenuPage.xaml.xs
using ProspectGator.Models;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ProspectGator.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuPage : ContentPage
{
MainPage RootPage { get => Application.Current.MainPage as MainPage; }
List<HomeMenuItem> menuItems;
public MenuPage()
{
InitializeComponent();
menuItems = new List<HomeMenuItem>
{
new HomeMenuItem {Id = MenuItemType.Browse, Title="Browse" },
new HomeMenuItem {Id = MenuItemType.About, Title="About" }
};
ListViewMenu.ItemsSource = menuItems;
ListViewMenu.SelectedItem = menuItems[0];
ListViewMenu.ItemSelected += async (sender, e) =>
{
if (e.SelectedItem == null)
return;
var id = (int)((HomeMenuItem)e.SelectedItem).Id;
await RootPage.NavigateFromMenu(id);
};
}
}
}
App.xaml.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using ProspectGator.Views;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace ProspectGator
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage( new MainPage());
}
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
}
}
}
Typically I would expect this property to be set or already set but I'm not sure. I do have a MainPage.xaml.
I am trying to build a webview app for one of my projects using Xamarin but I can't seem to figure out how to make the webview element go to previous page instead of closing the app.
So I have figured out how to detect the back button being pressed and prevent it from closing the app but I want to make the web page go back and if the web page can't go back then close the app.
Here's my code at the moment:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Application = Xamarin.Forms.Application;
namespace myNewApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public class WebPage : ContentPage
{
public object _browser { get; private set; }
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
return true;
}
public WebPage()
{
var browser = new Xamarin.Forms.WebView();
browser.Source = "https://myurl.com";
Content = browser;
}
}
}
I have tried a couple of answers and I found this bit of code but it doesn't work as the override can't access the public WebPage browser var:
if (browser.CanGoBack)
{
browser.GoBack();
return true;
}
else
{
base.OnBackButtonPressed();
return true;
}
Any help would be much appreciated.
you need to make browser a class level variable so you can access it anywhere in your page.
public class WebPage : ContentPage
{
Xamarin.Forms.Webview browser;
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
if (browser.CanGoBack)
{
browser.GoBack();
return true;
}
else
{
base.OnBackButtonPressed();
return true;
}
}
public WebPage()
{
browser = new Xamarin.Forms.WebView();
browser.Source = "https://myurl.com";
Content = browser;
}
}
I Have problem in my navigation drawer, so after my drawer menu is clicked, its go to another page but when im press back button then its make my application closed, what i want here is when im press the back button its go back to dashboard instead of close the application here is my code in navigation drawer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KGVC.Views.UsersInfo;
using System.Threading.Tasks;
using KGVC.Models;
using KGVC.Views.RssFeed;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace KGVC.Views.MainPages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : MasterDetailPage
{
public List<MasterPageItem> menuList { get; set; }
public MainPage()
{
InitializeComponent();
menuList = new List<MasterPageItem>();
// Creating our pages for menu navigation
// Here you can define title for item,
// icon on the left side, and page that you want to open after selection
var page0 = new MasterPageItem() { Title = "Dashboard", Icon = "icon_home.png", TargetType = typeof(MainPage) };
var page1 = new MasterPageItem() { Title = "Users Profile", Icon = "icon_home.png", TargetType = typeof(BioUsers) };
var page2 = new MasterPageItem() { Title = "Points", Icon = "icon_point.png", TargetType = typeof(RssFeedView) };
var page3 = new MasterPageItem() { Title = "Inbox", Icon = "icon_inbox.png", TargetType = typeof(TestPage1) };
var page4 = new MasterPageItem() { Title = "Card Community", Icon = "icon_community.png", TargetType = typeof(TestPage1) };
var page5 = new MasterPageItem() { Title = "Offers & Promotion", Icon = "icon_point.png", TargetType = typeof(Logout) };
var page6 = new MasterPageItem() { Title = "Info & Service", Icon = "icon_info", TargetType = typeof(Logout) };
// Adding menu items to menuList
menuList.Add(page0);
menuList.Add(page1);
menuList.Add(page2);
menuList.Add(page3);
menuList.Add(page4);
menuList.Add(page5);
menuList.Add(page6);
// Setting our list to be ItemSource for ListView in MainPage.xaml
navigationDrawerList.ItemsSource = menuList;
// Initial navigation, this can be used for our home page
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(GridMenu)));
}
private void OnMenuItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = (MasterPageItem)e.SelectedItem;
Type page = item.TargetType;
Detail = new NavigationPage((Page)Activator.CreateInstance(page));
IsPresented = false;
}
}
}
and here is my MasterPageItem class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace KGVC.Views.MainPages
{
public class MasterPageItem
{
public string Title { get; set; }
public string Icon { get; set; }
public Type TargetType { get; set; }
public ICommand Command { get; set; }
}
}
ho to make that happen, should i change anyting or is this possible to do that ?
Override the OnBackPressed in MainActivity(Android)
public override void OnBackPressed()
{
if(App.Instance.DoBack)
{
base.OnBackPressed();
}
}
In my xamarin forms app (App.Instance (it is a singleton))
public bool DoBack
{
get
{
MasterDetailPage mainPage = App.Current.MainPage as MasterDetailPage;
if (mainPage != null)
{
bool canDoBack = mainPage.Detail.Navigation.NavigationStack.Count > 1 || mainPage.IsPresented;
// we are on a top level page and the Master menu is NOT showing
if (!canDoBack)
{
// don't exit the app just show Dashboard
//mainPage.IsPresented = true;
Type page = typeof(MainPage);
mainPage.Detail = new NavigationPage((Page)Activator.CreateInstance(page));
return false;
}
else
{
return true;
}
}
return true;
}
}
--- Edited ---
static App _instance;
public static App Instance { get { return _instance; } }
Set _instance=this; in App()
Ive developing a webview app in Xamarin.Forms over the last few days and ive been testing it on an android and iOS emulator and it seems to work just fine in the emulators but when i went and tried to test it on my own Android device, it just showed the xamarin splashscreen(im using the trial version at the moment) and then just transitioned to a blank white screen instead of the webview.
Does anyone have any ideas why it is doing this?
I will attach my code below:
App.cs
using Xamarin.Forms;
namespace WebViewApp
{
public class App() : Application
{
public App()
{
// The root page of your application
MainPage = new WebPage();
}
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
}
}
}
WebPage.cs
using Xamarin.Forms;
namespace WebViewApp
{
public class WebPage : ContentPage
{
private const string URL = "https://www.google.com";
private const int PADDING_WIDTH = 0;
private int paddingHeight;
private WebView webView;
public WebPage()
{
webView = new WebView
{
Source = URL,
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand
};
CheckDevice();
Content = new StackLayout
{
Padding = new Thickness(PADDING_WIDTH, GetPaddingHeight()),
Chrildren = { webView }
};
}
public int GetPaddingHeight()
{
return paddingHeight;
}
/// <summary>
/// This will set the padding height for the webview when displayed
/// <summary>
/// <param name="pHeight">Set integer value for the padding height.</param>
public void SetPaddingHeight(int pHeight)
{
paddingHeight = pHeight;
}
private void CheckDevice()
{
if(Device.OS == TargetPlatform.Android)
{
SetPaddingHeight(0);
}
else if(Device.OS == TargetPlatform.iOS)
{
SetPaddingHeight(20);
}
}
}
}
** UPDATE **
I am using a company website but I have been testing this app out with a number of different sites such as google, youtube, and amazon. It would seem that the only site that wont display on my device is my companies website(its a responsive website) but all of the others do.
Since version 9, iOS will only allow your application to communicate with servers that implement best-practice security by default. Values must be set in Info.plist to enable communication with insecure servers.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads </key>
<true/>
</dict>
You must set the two properties HeightRequest and WidthRequest.
WebView requires that HeightRequest and WidthRequest are specified
when contained in StackLayout or RelativeLayout. If you fail to
specify those properties, the WebView will not render.
Source: https://developer.xamarin.com/guides/xamarin-forms/user-interface/webview/
Here is my code to display a webview in a Xamarin.Forms App.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin;
using Xamarin.Forms;
namespace mynamespace
{
public class WebsitePage : ContentPage
{
public WebsitePage(string url)
{
Label lbl_header = new Label
{
Text = "WebView",
HorizontalOptions = LayoutOptions.Center
};
WebView webview = new WebView
{
Source = url,
VerticalOptions = LayoutOptions.FillAndExpand
};
this.Content = new StackLayout
{
Children = {
webview
}
};
}
}
}