How to handle screen rotation/orientation in Xamarin Forms? - xamarin

Is there a (half) generic way to handle rotation/orientation in Xamarin Forms for different views and platforms (Android, iOS, WinPhone)?
The UI does rotate, and that is nice enough, though it wreaks havoc to my layout (absolute layout right now). I suppose with a Stacklayout I could make it a litte more flexible, but would then hit a road block somewhere else when the layout is more intricate.
Can I somehow display different views for portrait and landscape, with the same ViewModel? (I am using XLABs based MVVM.)
Possible solutions I have found:
http://blog.rthand.com/post/2014/07/24/Different-XAML-layouts-for-different-device-orienations-in-XamarinForms.aspx is lacking iOS and I wonder if it will handle MVVM too well, seems good though and I am investigating it right now
http://www.jimbobbennett.io/orientation-with-xamarin-forms/ sounds promising but the sample is iOS only, the linked GIT repository has no documentation at all, it just says "Xamarin Helpers"
http://www.sellsbrothers.com/posts/Details/13740 might also be a possibility for programmatically created views. Though in my tests I did not get a size changed event (though I listened at a different code place) for ios simulator when rotating. (The solution is based on size changed to detect rotation.)

If you are already using XLabs then you could use IXFormsApp and property 'Orientation' and event handler 'Rotation'. You would have to add the native observers per platform and set IXFormsApp's 'Orientation' there which would cause the event handler to invoke.
For example on iOS:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
var xapp = new XFormsAppiOS();
xapp.Init(this);
var resolverContainer = new SimpleContainer();
resolverContainer.Register<IXFormsApp>(xapp);
Resolver.SetResolver(resolverContainer.GetResolver());
var a = new App();
LoadApplication(a);
UIDevice.Notifications.ObserveOrientationDidChange((s, e) =>
{
xapp.Orientation = ... // set orientation here
});
Now you can monitor orientation changes by resolving IXFormsApp:
xapp = Resolver.Resolve<IXFormsApp>();
if (xapp.Orientation == Orientation.Landscape) { ... } else { ... }
xapp.Rotation += (sender, args) =>
{
switch (args.Value)
{
case Orientation.LandscapeLeft:
break;
default:
// etc.
break;
}
};
As for layouts I would imagine RelativeLayout would be the most convenient choice as you could put the orientation inside the Constraint's. On rotation make the layout refresh itself.

Related

Xamarin Forms, Detecting map Scrolling, Zooming and etc event

I'm using Xamarin Forms Maps official nuget library, everything works good and I handle finish zooming and scrolling map via this code:
map.PropertyChanged += (sender, args) =>
{
var m = sender as Map;
if (m?.VisibleRegion == null) return;
SearchButton.IsVisible = true;
};
map.PropertyChanging += (sender, args) => { SearchButton.IsVisible = false; };
But I want to do some stuff when user starts scrolling or zooming map!
I didn't find it and also PropertyChanging not called when user is surfing the map, it's calling just before PropertyChanged.
I think in Xamarin.Forms your options are limited, so your best option would be to either create a custom renderer and abstract the gestures into Xamarin.Forms, or create your own custom canvas, render the map onto it and that way you would have full control.

How to present an iOS Modal View in MvvmCross

How can I present a modal view on iOS using MvvmCross?
Using Xamarin Studio on iOS and the MvvmCross NuGet version 4.2.2, none of the MvxModalSupportTouchViewPresenter, MvxModalNavSupportTouchViewPresenter or IMvxModalTouchView are even available.
Does the ViewModel even need to know about the fact that a particular view is presented as a modal view on iOS?
MvvmCross is a strong Page navigation framework. Default navigation using ShowViewModel<AViewModel> will use the stack metaphor: one on top of another on Android, slide atop each other on iOS, and use < on either platform to go back.
You can tell the ViewPresenter that a given view is modal by giving it a hint, in the form of an interface marker, by adopting IMvxModalIosView.
At the View Level
Adopt the IMvxModalIosView protocol:
public partial class AView : MvxViewController, IMvxModalIosView
At the AppDelegate Level
Replace var setup = new Setup(this, Window) by:
var presenter = new MvxModalSupportIosViewPresenter(this, Window);
var setup = new Setup(this, presenter);
setup.Initialize();
At the ViewModel Level
No change required. The ViewModel is actually not made aware of the modal presentation. Invoke:
ShowViewModel<AViewModel> // May be modal on certain platforms
To close a Page and go back to the previous one, regardless of your presentation style, use Close(this) on that very ViewModel. This will close a modal dialog, or pop a pushed view. A complete, bindable ICommand may look like this:
public ICommand BackCommand {
get { return new MvxCommand(() => Close(this)); }
}
Notes: In MvvmCross 4.2.2, Touch has been renamed iOS, so IMvxModalTouchView is now IMvxModalIosView. The new using are:
using MvvmCross.iOS.Platform;
using MvvmCross.iOS.Views.Presenters;
Using MvvmCross 5.5.2 all I had to get a modal was to add the following MvxModalPresentation attribute to my iOS view:
[Register("ExampleModalView")]
[MvxModalPresentation(
ModalPresentationStyle = UIModalPresentationStyle.PageSheet,
ModalTransitionStyle = UIModalTransitionStyle.CoverVertical
)]
public class ExampleModalView : MvxViewController
{
public ExampleModalView() {
}
...
}
Launching the modal is simple with the IMvxNavigationService service
await _navigationService.Navigate<ExampleModalViewModel>();
ExampleModalViewModel just needs to be a plain MvvmCross view model inheriting from MvxViewModel.
A useful reference for this is ModalView.cs in the iOS playground project: https://github.com/MvvmCross/MvvmCross/blob/develop/TestProjects/Playground/Playground.iOS/Views/ModalView.cs#L12

Xamarin forms background image for all Pages

It´s possible to set an image to be the background of all Pages on my application (for all platforms IOS, Android and WP) ?
Page has a BackgroundImage property, so I can create a base page, set the background and make all my pages extends from it.
I want to know if there is a more appropriate solution, to handle this.
You could use Styles in your App.cs :
public App ()
{
Application.Current.Resources.Add(new Xamarin.Forms.Style(typeof(Page)){
Setters = {
new Xamarin.Forms.Setter { Property = Page.BackgroundImageProperty, Value = "back.png"},
}
});
}
much less preferred or advised but for the sake of showing another option you could attach an event handler to your NavigationPages and set the background from there:
yourRootNavigationPage.Pushed+= (sender, e) => e.Page.BackgroundImage = "back.png";

Capture touch events in Xamarin.Forms for Android

I am creating an app that allows the user to drag and drop to put one image on top of another using Xamarin.Forms.
On iOS I managed to hack together a workable gesture recognizer renderer by creating a custom ContentView and a custom renderer for it, which then attaches native gesture recognizers to itself based on the GestureRecognizers elements. To do that I disable the default EventTracker and implement my own, with overridden GetNativeRecognizer method
in the custom renderer:
public InteractiveContentViewRenderer () : base ()
{
AutoTrack = false;
events = new InteractiveEventTracker (this);
}
in the custom event tracker:
public InteractiveEventTracker (IVisualElementRenderer renderer) : base (renderer)
{
this.Renderer = renderer;
}
protected override MonoTouch.UIKit.UIGestureRecognizer GetNativeRecognizer (Xamarin.Forms.IGestureRecognizer recognizer)
{
var gestureRecognizer = base.GetNativeRecognizer (recognizer);
if (gestureRecognizer == null) {
// here I find my own native recognizer and return it
}
}
On Android, however, so far I haven't figured out how to achieve the same thing. There's no EventTracker in Android, I think I'll have to implement some Android View for this to work but I haven't figured it out so far.
Has anyone managed to hack together touch events in Xamarin.Forms for Android? I'd like to know at least the basic structure of the hack?
Read this: http://blog.twintechs.com/cross-platform-compositional-gesture-advanced-xamarin-forms-techniques-for-flexible-and-performant-cross-platform-apps-part-4
There's a lot about custom gestures in Xamarin.Forms
The source is here: https://github.com/twintechs/TwinTechsFormsLib/tree/master/TwinTechsForms/TwinTechsForms.Droid/TwinTechs/Gestures

how to show the aspx design in flex 4.6/how to retrieve the aspx page in to flash buildr 4.6

In my project we need to retrieve/show the aspx page in flash builder 4.6 and we are trying the code like in mxml application(main page)...
protected function imgtesting_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
var win:Imageview=PopUpManager.createPopUp(this ,Imageview,true) as Imageview;
win.testobjpckt=this;
PopUpManager.centerPopUp(win);
}
and in title window(popup) the code is like....
<dgFooter:IFrame id="iframe" width="984"
height="352" autoResize="true"
horizontalScrollPolicy="off"
overlayDetection="true"
url="http://localhost/......../Default.aspx"
verticalScrollPolicy="off"/>
Here we are able to get the aspx page in to flashbuilder 4.6 and we are able to show the controls of aspx page and those controls are also working and the ISSUE is:
"DESIGN:THE DESIGN OF THE ASPX PAGE IS OVERLAPPING ON THE POPUP(TITLE WINDOW) AND POSITION OF THE CONTROLS ARE ALSO CHANGING IN FLASH BUILDER AND THE ASPX WHOLE PAGE DESIGN IS CHANGING(IN THE SENSE POSITIONS OF CONTROLS ARE CHANGING) SO WE ARE REALLY STRUGGLING A LOT TO GET THE DESIGN IN TO FLASH BUILDER PROPERLY FROM VISUAL STUDIO TO FLASH BUILDER".
SO WE REALLY NEED A SOLUTION TO SOLVE THIS ISSUE.IF ANY HELP I WILL THANKFUL TO THEM A LOT...
Finally i got the solution for the designing,what i did is...
I just changed the Action-script file for IFRAME by adjusting the x,y coordinates like..
override protected function commitProperties():void
{
super.commitProperties();
if(positionChanged)
{
var point:Point = localToGlobal(new Point(154,24));
callJS(methodMove, point.x, point.y);
positionChanged = false;
}
if(sizeChanged)
{
callJS(methodResize, width, height);
sizeChanged = true;
}
}
so,this makes my issue solved......

Resources