Displaying Image on navigation bar and page xamarin forms - c#

Using Xamarin Forms 2.5.0.122203, I want to achieve to add an image that is half over navigation bar and another half in the page like this image
I tried Negative margin and it only worked on UWP. Unfortunately, iOS and Android cut image.
I was thinking of creating a custom navigation bar but the thing is UWP has this bug that doesn't hide native Navigation right.
Any solution?
Thank you

I ended up Copying SNavigation.Forms to my projects.
After following their documentation.
In the Page I override
protected override void OnBindingContextChanged()
{
if (BindingContext == null)
{
return;
}
base.OnBindingContextChanged();
SNavigationPage.SetNavContent(this, new LogoHeader()
{
BindingContext = BindingContext,
});
}
The LogoHeader is the intended layout to be postioned in the Navigation (Better use a Grid)
Visually I have one Navigation Header but technically it is cut in half.
It took a lot of time to get the perfect result because you have to remove all navigation shadows from Android and iOS but it is a reliable solution

Related

How to swipe back in Xamarin.iOS?

I have a ContentPage with a WebView in my shared Xamarin project.
To enable Android's back button within the WebView, I used the following code:
protected override bool OnBackButtonPressed()
{
_myWebView.GoBack();
return true;
}
As we all know, iOS does not have a back button. I want to enable swiping left in order to navigate to the previous Webview page.
What is the easiest way or approach?
I would suggest implementing a custom renderer for the WebView and attach a gesture recognizer to the underlying UIWebView. This is how the WebViewRenderer for iOS is implemented in Xamarin Forms.
The Xamarin Forms WebView is actually a UIWebView on iOS. So you can implement the Swift code from the following answer in your renderer: https://stackoverflow.com/a/32012660/6192895. Converting this Swift code to C# is fairly trivial, but this is also a potential solution:
Basic solution
public class SwipeWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
var view = NativeView as UIWebView;
var swipeBackRecognizer = new UISwipeGestureRecognizer(HandleSwipeBack);
swipeBackRecognizer.Direction = UISwipeGestureRecognizerDirection.Right;
view.AddGestureRecognizer(swipeBackRecognizer);
}
void HandleSwipeBack()
{
(Element as WebView).GoBack();
}
}
This solution is fairly basic, it just does the GoBack() action without actually showing the swipe of the page like the normal Safari browser does. So you might have to add some more code if that's what you need.
Transitioning
You can make use of CoreAnimation for this. Use this as your HandleSwipeBack method:
void HandleSwipeBack()
{
CATransition animation = new CATransition();
animation.Type = CAAnimation.TransitionPush;
animation.Subtype = CAAnimation.TransitionFromLeft;
animation.Duration = 0.50;
animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
(NativeView as UIWebView).Layer.AddAnimation(animation, CALayer.Transition);
(Element as WebView).GoBack();
}
This will not get you the exact same behaviour as the Safari browser, as it will not cancel the animation if you stop the swipe halfway for example. It is possible to do so, but it would require more code.
Extra information
You might also be able to draw some inspiration from this Pull Request for a SwipeGestureRecognizer, which was not included in Xamarin Forms because unit tests and UI tests were missing.
Unfortunately the default Xamarin Forms GestureRecognizers are limited to Tap, Pinch and Pan for the moment.
Can you try the following
NavigationPage.SetBackButtonTitle (this, "")
or alternatively you can add tool bar item and then try something like this
ToolbarItems.Add(new ToolbarItem("Back", "BackIcon.png", () => { _webview.GoBack(); }));

Xamarin Forms ScrollView click always sets Focus on first item of child Grid

I have a scrollView with a Grid inside which contains several Entrys.
When I click anywhere on the screen that isn't one of the Entry controls the focus automatically goes to the first Entry I have on the grid. I.e. This happens whether any Entry already has Focus or not, it will always set the focus of the first one again.
If I remove the Scrollview and have the Grid on screen on it's own I don't get this issue.
I am developing an application for a Windows 10 device but using the Xamarin forms cross platform code as we may move the code to Android at some stage.
Thanks in advance.
I was able to reproduce the described behavior on UWP Windows 10, but not on Android or iOS, so this is a bug in the Forms code for UWP.
I have filed a bug report for this issue which you can track here: https://bugzilla.xamarin.com/show_bug.cgi?id=52613
Xamarin engineers will now discuss this issue on the bug report. If you would like to receive a notification when the bug is updated, you can add yourself to the CC list for the bug. Please note that you will need to create an account on that system if you have not already done so.
I don't know if you solved your problem because it was more than a year ago and the issue #jgoldberger has opened on Xamarin's Bugzilla did not progress since last October.
Nevertheless I just noticed the same behaviour on my UWP app and after looking around the internet I found a solution.
If you look at this thread : Why does my TextBox get focused when clicking inside of ScrollViewer?
Then it is easy to imagine a solution for a Xamarin.Forms app by creating a custom renderer inside your UWP project.
You can use the following code which is working perfect for me :)
using {your_project_namespace}.UWP;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(ScrollView), typeof(ScrollViewCustomRenderer))]
namespace {your_project_namespace}.UWP
{
public class ScrollViewCustomRenderer : ScrollViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e)
{
base.OnElementChanged(e);
if (Control == null)
return;
Control.IsTabStop = true;
}
}
}
Hope this helps.
Cheers

How to apply Xamarin Platform-Specific EnableTranslucentNavigationBar

I'm testing out Xamarin Forms's new Platform-Specifics features (in 2.3.3). In particular, the EnableTranslucentNavigationBar.
I have a RootPage object that is a MasterDetail. The Detail is a NavigationPage. Here's my relevant App() ctor code:
public App()
{
InitializeComponent();
//Note: RootPage is MasterDetail, Detail is NavigationPage
var rootPage = new RootPage();
(rootPage.Detail as NavigationPage).On<iOS>().EnableTranslucentNavigationBar();
MainPage = rootPage;
}
This however is not applying the translucent navigation bar effect on the NavigationPage. It is still a solid color (default white) and the content doesn't scroll up
Is there a specific place/time I need to apply this?
Side Note: While working on this, I also noticed a weird ambiguity between two different NavigationPage objects. One in Xamarin.Forms.NavigationPage and one in Xamarin.Forms.PlatformConfiguration.iOSSpecific.NavigationPage. I eventually got the method to use the former, but it made me think that I might need to cast it first...
UPDATE:
Xamarin reports this should be fixed in 2.3.4-pre1
Xamarin has confirmed this is an issue in Xamarin.Forms 2.3.3 and are investigating. Go here to see the Bugzilla report.
I will update this post once I hear back from them regarding a fix or workaround.
UPDATE
Should be fixed in 2.3.4-pre1

Windows Phone navigation buttons overlap with screen resolution

below you'll see a screen running in Windows Phone 8.1 one 2 devices. Both are claiming to have Viewport Width and Height of 800x480 however as you can see from the image the 635's nav buttons are overlapping the game area.
I have checked various properties in GraphicsDevice.Adapter and GraphicsDevice.Viewport, but they are both the same!
The screen is running within C# UWP Monogame code. I set the PrefferedBackBufferWidth and Height to 480x800.
How can you tell if the nav buttons with take up part of the screen?
I will expand the answer further.
In windows phone 8.1, you have two ApplicationViewBoundsMode enum values.
UseVisible, pages inside application will use only the visible area excluding StatusBar, application bar and Soft navigation buttons.
To make your app use ApplicationViewBoundsMode.UseVisible option, add the following in app.xaml.cs before `Windows.Current.Activate();
#if WINDOWS_PHONE_APP
ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseVisible);
#endif
UseCoreWindow, lay out the window's content within the region occupied by the core window (that is, including any occluded areas- including soft navigation buttons).
To make your app use ApplicationViewBoundsMode.UseCoreWindow option, add the following in app.xaml.cs before Windows.Current.Activate();
#if WINDOWS_PHONE_APP
ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseCoreWindow);
#endif
In some cases, developers may want to use UserCoreWindow option to show content under app bar but as a side effect navigation soft buttons will occlude parts of your page to resolve it, follow the next solution.
You can listen for ApplicationView.GetForCurrentView().VisibleBoundsChanged in WindowsPhone and update the margin of your page.
Here is an article written by Joost van on fixing this issue (and a behavior that you can use out of the box)
Quoting the issue explanation from the above link
If the application view bound mode is set to ApplicationViewBoundsMode.UseCoreWindow in App.Xaml.cs the phone reports the whole screen size – not only the part that is normally taken by the status bar on top and the application bar at the bottom, but also the part that is used by the button bar.
And a snippet from his solution where he updates the margin of page
void KeepInViewBehaviorVisibleBoundsChanged(ApplicationView sender, object args)
{
UpdateBottomMargin();
}
private void UpdateBottomMargin()
{
if (WindowHeight > 0.01)
{
var currentMargins = AssociatedObject.Margin;
var newMargin = new Thickness(
currentMargins.Left, currentMargins.Top, currentMargins.Right,
originalBottomMargin +
(WindowHeight - ApplicationView.GetForCurrentView().VisibleBounds.Bottom));
AssociatedObject.Margin = newMargin;
}
}
to hide the navigation bar in your monogame windows phone 8.1 game add the following code in your app.xaml.cs file under InitializePhoneApplication() method
RootFrame = new PhoneApplicationFrame();
//I have set it to RootVisual to hide navigationbar
RootFrame.FullScreen = true;
if (RootVisual != RootFrame)
RootVisual = RootFrame;

Xamarin Forms Android System Exception "Android only allows one navigation page on screen at a time"

Recently i decided to give Xamarin Forms a try, so i started migrating my Windows Phone / Android Xamarin project, to the new "Forms" format.
After migrating two simple screens (views), the code runs just fine on my Windows Phone, but it crashes on the Android Platform. I am using two devices to test the code, with no emulator to avoid unecessary headaches.
The exception raised on the android platform is: System.Exception: Android only allows one navigation page on screen at a time.
The problem is not related to the "View" class itself, since it doesn`t happen once i set it as the "start screen" for the Android.
I'm afraid the problem is related to the fact that i am "Pushing" two screens via the "Navigation.PushAsync(...)" method provided by Xamarin.
Any ideas on how do actually fix it ?
EDIT:
Code Sample
Overview: The "MainView.cs" is just a content page with a label on the top, followed by two buttons alligned vertically.
How to reproduce the exception: Click on "Get All Users" button on the mainview. I have modified the code to push the same view once the button is clicked, instead of pushing another view (The view that has a listview of users, which i haven't included, just to make it simple). Once the button is clicked, it will navigate to a new instance of "MainView" by calling "Navigation.PushAsync(...)". This will trigger the exception after the screen is loaded.
You are nesting Navigation pages. This is not necessary. Try this instead:
public class ViewsHandler
{
public static Page GetMainPage()
{
return new MainView();
}
public static Page GetUsersListPage()
{
return new UsersListView ();
}
}
public class MainActivity : AndroidActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Initializing Xamarin Form
Xamarin.Forms.Forms.Init (this, bundle);
// create a single NavigationPage wrapping your content
SetPage (new NavigationPage(ViewsHandler.GetMainPage()));
}
}

Categories

Resources