how would I use Dependency Injection to use the Flyoutnavigation for my iOS project.
I have decided to stick with the default MasterDetailPage for Android as it doesn't look as bad as iOS.
This is what I have done so far:
In PCL
IMainPage.cs:
public interface IMainPage
{
Page GetMainPage();
}
App.cs:
public partial class App : Application
{
public App()
{
MainPage = DependencyService.Get<IMainPage>().GetMainPage();
}
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
}
}
In Android
MainPage_Android.cs:
[assembly: Xamarin.Forms.Dependency(typeof(MainPage_Android))]
namespace ProjectName.Droid
{
public class MainPage_Android : MasterDetailPage, IMainPage
{
private NavigationPage detail;
private MasterPage master;
public Page GetMainPage()
{
MasterDetailPage mdp = new MasterDetailPage();
//Master
master = new MasterPage();
MasterBehavior = MasterBehavior.Popover;
mdp.Master = master;
//Detail
detail = new NavigationPage(new Home())
{
BarBackgroundColor = Color.FromHex("#01A0E1"),
BarTextColor = Color.White
};
mdp.Detail = detail;
return mdp;
}
}
}
In iOS
I am stuck here.. How do I return a page using the Flyoutnavigation?
If you want to use default style on Android and custom style on iOS, you can try to make a custom renderer for MasterDetailPage on iOS. Then embed your Flyoutnavigation.
This is my iPad renderer:
[assembly: ExportRenderer(typeof(MainPage), typeof(MainPageRenderer))]
namespace FlyoutNavigationDemo.iOS
{
public class MainPageRenderer : TabletMasterDetailRenderer
{
//put your Flyoutnavigation's code here
}
}
Since Flyoutnavigation has too much code. I make a small sample for you, you can refer to here for more details.
Related
I use bottom menu and disable flyout.
For IOS I needed to add swipe gesture to shell. I used custom render.
How to add swipe animation?
On Android for tabbed page it works out of box.
I need something similar for Xamarin Shell tabbar menu.
I thought Xamarin Forms is pretty easy to use without any problems. It’s basic thing it should be implemented
[assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
namespace ShellDemo.iOS
{
public class CustomShellRenderer : ShellRenderer
{
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new CustomTabbarAppearance();
}
}
public class CustomTabbarAppearance : IShellTabBarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(UITabBarController controller)
{
}
public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
UISwipeGestureRecognizer swipeRight = new UISwipeGestureRecognizer((gesture) =>
{
if (controller.SelectedIndex > 0)
{
controller.SelectedIndex--;
}
});
swipeRight.Direction = UISwipeGestureRecognizerDirection.Right;
controller.View.AddGestureRecognizer(swipeRight);
UISwipeGestureRecognizer swipeLeft = new UISwipeGestureRecognizer((gesture) =>
{
if (controller.SelectedIndex < controller.ViewControllers.Count() - 1)
{
controller.SelectedIndex++;
}
});
swipeLeft.Direction = UISwipeGestureRecognizerDirection.Left;
controller.View.AddGestureRecognizer(swipeLeft);
}
public void UpdateLayout(UITabBarController controller)
{
}
}
}```
![enter image description here](https://i.stack.imgur.com/dXNMJ.gif)
I am working on xamarin forms. I wanted to change the Toolbar back icon how to do it. I searched lot about it. I didn't get proper solution. Any help would be appreciated.
Thanks
praveen
Try this
LoadApplication(new App());
var upArrow = Resources.GetDrawable(Resource.Drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.SetColorFilter(Resources.GetColor(Resource.Color.white), PorterDuff.Mode.SrcIn);
ActionBar.SetHomeAsUpIndicator(upArrow);
References
https://forums.xamarin.com/discussion/57791/cant-change-android-back-button-in-xamarin-forms
https://forums.xamarin.com/discussion/103317/change-navigation-bar-back-button-color-in-xamarin-android
How to change the toolbar back icon in xamarin forms android
You could refer to my answer: How to change navigation page back button in xamarin forms.
I write it here again:
We need to custom a NavigationPageRenderer, override the OnPushAsync method to set the Toolbar's navigation icon.
using AToolbar = Android.Support.V7.Widget.Toolbar;
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(NavigationPageRendererDroid))] // APPCOMP
...
public class NavigationPageRendererDroid : Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer // APPCOMP
{
public AToolbar toolbar;
public Activity context;
protected override Task<bool> OnPushAsync(Page view, bool animated)
{
var retVal = base.OnPushAsync(view, animated);
context = (Activity)Xamarin.Forms.Forms.Context;
toolbar = context.FindViewById<Android.Support.V7.Widget.Toolbar>(Droid.Resource.Id.toolbar);
if (toolbar != null)
{
if (toolbar.NavigationIcon != null)
{
toolbar.NavigationIcon = Android.Support.V4.Content.ContextCompat.GetDrawable(context, Resource.Drawable.Back);
//toolbar.SetNavigationIcon(Resource.Drawable.Back);
}
}
return retVal;
}
}
The CustomNavigationPage are defined in PCL :
public class CustomNavigationPage : NavigationPage
{
public CustomNavigationPage(Page startupPage) : base(startupPage)
{
}
}
Usage :
public App()
{
InitializeComponent();
MainPage = new CustomNavigationPage(new MainPage());
}
...
// In MainPage
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new TestPage());
}
[Effect].
i want to change navigation bar title icon on my xamarin.forms ios application.You can find requested point at the attached image.app_screenshot
You can achieve this by using Custom Renderers on Xamarin.Forms. Since each UIViewController has its own NavigationItem, you should do this in your particular page which you want to modify its LeftBarButtonItem. Here is my Renderer for you referring to:
[assembly: ExportRenderer(typeof(CustomPage), typeof(CustomPageRenderer))]
namespace UIBarButtomItemsForms.iOS
{
public class CustomPageRenderer : PageRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var navigationItem = NavigationController.TopViewController.NavigationItem;
UIBarButtonItem leftItem = new UIBarButtonItem(UIImage.FromBundle("Image.png"), UIBarButtonItemStyle.Plain, (sender, args) =>
{
});
navigationItem.SetLeftBarButtonItem(leftItem, false);
}
}
}
Then on Forms you can use this CustomPage, please notice that you should make your MainPage wrapped in a NavigationPage: MainPage = new NavigationPage(new MainPage());
Take a look at Change the Back Button: https://developer.xamarin.com/recipes/ios/content_controls/navigation_controller/change_the_back_button/
I want to open Xamarin forms page from Xamarin Android project. On android project I created toolabar item image, where I am calling event to open page from Xamarin forms project.
Here is my MainActivity.cs toolabar image item implementation:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
private IMenu CurrentMenu { get; set; }
private ImageView imgSmallC { get; set; }
public override bool OnCreateOptionsMenu(IMenu menu)
{
ActionBar.DisplayOptions = ActionBarDisplayOptions.HomeAsUp | ActionBarDisplayOptions.ShowCustom | ActionBarDisplayOptions.ShowTitle | ActionBarDisplayOptions.ShowHome;
LayoutInflater inflater = (LayoutInflater)ActionBar.ThemedContext.GetSystemService(LayoutInflaterService);
View customActionBarView = inflater.Inflate(Resource.Layout.actionbar_custom_view_done, null);
imgSmallC = (ImageView)customActionBarView.FindViewById<ImageView>(Resource.Id.ImgSmallC);
imgSmallC.Click += (object sender, EventArgs args) =>
{
StartActivity(typeof(MyPopupPage));
};
return base.OnCreateOptionsMenu(menu);
}
}
In StartActivity I am calling MyPopupPage.xaml page from Xamarin forms project, but unfortunately when I am debugging project and I click on toolbar image I get such a error:
System.ArgumentException: type Parameter name: Type is not derived
from a java type.
You can not use a Xamarin.Form based Page as an Android Activity, they are two completely different things.
You can access the Xamarin.Forms Application singleton from the Xamarin.Android project and use that to PushModelAsync or PushAsync
Example (using full Namespace):
await Xamarin.Forms.Application.Current.MainPage.Navigation.PushModalAsync(new PushPageFromNative.MyPage());
A Dependency Service-based Example:
Interface:
using System;
namespace PushPageFromNative
{
public interface IShowForm
{
void PushPage();
}
}
Xamarin.Form-based code:
var pushFormBtn = new Button
{
Text = "Push Form",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
pushFormBtn.Clicked += (sender, e) =>
{
DependencyService.Get<IShowForm>().PushPage();
};
Xamarin.Android Dependancy Implementation:
async public void PushPage()
{
// Do some Android specific things... and then push a new Forms' Page
await Xamarin.Forms.Application.Current.MainPage.Navigation.PushModalAsync(new PushPageFromNative.MyPage());
}
I have a strange recurring problem. Sometimes it goes away, other times it comes back. I can't pinpoint at all the issue, all my breakpoints seem to be hit in expected order.
When I navigate to a new page, my backstack keeps getting deleted, so pressing back just backgrounds the app. Obviously this is a problem.
I think it may be a result of my more complex page and viewmodel structures. I created a new class for all the NavigationHelper stuff for Pages enforcing that all my Pages subclass from the new class. I enforce that all my Pages attach themselves to a base PageViewModel class to resolve the communication between the two (I had a better way but Xaml doesn't play well), and I navigate using a NavigationService, where I call CurrentFrame, which is a static method for return Windows.Current.Content as Frame.
Here are what I think are relevant code. Any ideas? Thanks a bunch in advance. I have no clue what's going on :/
I navigate forward using the Navigate method in NavigationService (not the other two lolol), but my back button doesn't go back properly.
public abstract class BaseViewModelPage : Page
{
protected readonly NavigationHelper NavigationHelper;
protected BaseViewModelPage()
{
NavigationHelper = new NavigationHelper(this);
NavigationHelper.LoadState += navigationHelper_LoadState;
NavigationHelper.SaveState += navigationHelper_SaveState;
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected BasePageViewModel CurrentPageViewModel
{
get { return DataContext as BasePageViewModel; }
}
#region Navigation Registration
protected override void OnNavigatedTo(NavigationEventArgs e)
{
NavigationHelper.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
NavigationHelper.OnNavigatedFrom(e);
}
protected virtual void LoadState(LoadStateEventArgs e)
{
if (CurrentPageViewModel != null)
{
CurrentPageViewModel.LoadState(e);
}
}
protected virtual void SaveState(SaveStateEventArgs e)
{
if (CurrentPageViewModel != null)
{
CurrentPageViewModel.SaveState(e);
}
}
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
LoadState(e);
}
private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
{
SaveState(e);
}
#endregion
}
public abstract class BasePageViewModel : ViewModelBase
{
private bool _isLoading = false;
public bool IsLoading
{
get
{
return _isLoading;
}
set
{
if (_isLoading == value)
{
return;
}
_isLoading = value;
RaisePropertyChanged();
}
}
public virtual void LoadState(LoadStateEventArgs e)
{
}
public virtual void SaveState(SaveStateEventArgs e)
{
}
}
public class NavigationService : INavigationService
{
public static readonly Dictionary<Type, Type> PageDictionary;
static NavigationService()
{
PageDictionary = new Dictionary<Type, Type>();
PageDictionary.Add(typeof(LogInPageViewModel), typeof(LogInPage));
PageDictionary.Add(typeof(RegisterUserPageViewModel), typeof(RegisterUserPage));
}
public bool Navigate(Type pageViewModelType, Object parameter = null)
{
if (PageDictionary.ContainsKey(pageViewModelType))
{
if (parameter != null)
{
return App.CurrentFrame.Navigate(PageDictionary[pageViewModelType], parameter);
}
else
{
return App.CurrentFrame.Navigate(PageDictionary[pageViewModelType]);
}
}
return false;
}
public bool GoBack()
{
if (CanGoBack())
{
App.CurrentFrame.GoBack();
}
return false;
}
public bool CanGoBack()
{
return App.CurrentFrame.CanGoBack;
}
public bool NavigateAndRemoveSelf(Type pageViewModelType, object parameter = null)
{
if (Navigate(pageViewModelType, parameter))
{
if (App.CurrentFrame.CanGoBack)
{
App.CurrentFrame.BackStack.RemoveAt(App.CurrentFrame.BackStackDepth - 1);
return true;
}
}
return false;
}
public bool NavigateAndRemoveAll(Type pageViewModelType, object parameter = null)
{
if (Navigate(pageViewModelType, parameter))
{
while (App.CurrentFrame.CanGoBack)
{
App.CurrentFrame.BackStack.RemoveAt(App.CurrentFrame.BackStackDepth - 1);
}
return true;
}
return false;
}
}
Update [solved]:
The error is caused by using a Universal App Class Library.
I wanted to separate the NavigationHelper.cs class (generated by default in WP8 apps) into a library. so that I could unit test the VM directly (I could not reference the WP8 app with the Unit Test project). Thus, I placed the NavigationHelper.cs class, plus all my relevant code above, in a new Universal App Class Library.
The NavigationHelper class relies on two things, a WINDOWS_PHONE_APP macro in the BUILD, which affects this specific part in the NavigationHelper class, the HardwareButton BackPressed listener.
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#else
and a second reliance on the Windows.Phone assembly. The assembly exists in a WP8 app, but not for a Universal App Class Library. This means that even if I add the WINDOWS_PHONE_APP macro to the library, the app will not compile. You cannot use the NavigationHelper generated by Windows Phone 8/8.1 projects inside a Universal App Class Library. I will try to raise this issue. Thanks!
Update [solved]:
The error is caused by using a Universal App Class Library.
I wanted to separate the NavigationHelper.cs class (generated by default in WP8 apps) into a library. so that I could unit test the VM directly (I could not reference the WP8 app with the Unit Test project). Thus, I placed the NavigationHelper.cs class, plus all my relevant code above, in a new Universal App Class Library.
The NavigationHelper class relies on two things, a WINDOWS_PHONE_APP macro in the BUILD, which affects this specific part in the NavigationHelper class, the HardwareButton BackPressed listener.
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#else
...
#endif
Because the MACRO wasn't defined, the back button wouldn't actually go back.
A second problem was the missing Windows.Phone assembly. The assembly exists in a WP8 app, but not for a Universal App Class Library. This means that even if I add a WINDOWS_PHONE_APP macro to the library, the app will not compile. You cannot use the NavigationHelper generated by Windows Phone 8/8.1 projects inside a Universal App Class Library. I will try to raise this issue. Thanks!
You can leave your NavigationHelper in your shared project, just add this to your MainPage in the Windows Phone project..
static MainPage()
{
HardwareButtons.BackPressed += (sender, args) =>
{
var frame = Window.Current.Content as Frame;
if (frame != null && frame.CanGoBack)
{
frame.GoBack();
args.Handled = true;
}
};
}
This solved my BackButton issues.