There is a image control in my page, which support the landscape and portrait layout. I want implement an animation that rotate the image when the oritentaion changed. Which just like the built-in rotate animation of applicationbar. But I have no any idea right now. Could anyone give me a hand?
There are at least two ways to implement it:
1) Catch the OrientationChanged event and animate layout using Fluid UI feature in Expression Blend. It allows you to make smooth transition from one visual state to another.
void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e) {
if(Orientation==PageOrientation.PortraitUp) {
VisualStateManager.GoToState(this, "VisualStatePortrait", true);
}
else {
VisualStateManager.GoToState(this, "VisualStateLandscape", true);
}
}
You should also define visual states for landscape and portrait layout. More on how to declare them you may find out from this video.
2) Another approach introduced by a Windows Phone developer from Microsoft. His solution requires additional code but is more customizible: you can choose between rotation, fade or hybrid animation. A code sample is also included.
Related
in my app I allow the multitasking mode.
But I need to do some action if my view is too restricted.
Watching Apple documentation I saw this image
You can see that in iPad Pro in SplitView, both views are regular, instead in other iPads both views are compact.
I there something that allow me to know if my current view is regular or compact?
Thanks
This is my solution:
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular){
NSLog(#"REGULAR HORIZONTAL");
return TRUE;
}else{
NSLog(#"COMPACT HORIZONTAL");
return FALSE;
}
If you need to handle it programatically, you can override -traitCollectionDidChange: and look at the self.traitCollection property on that view and make changes depending on the output.
However -viewWillTransitionToSize:withTransitionCoordinator: will get you a more fine grained response to how big the view controller has been resized to.
It would be great to have library that both:
uses new 3D Touch api on iPhone 6s
on older devices emulates peek and pop with some gestures.
Advantages:
users of older devices could benefit from new interface possibilities
adoption of peek and pop would be faster - no need to wait years till everybody has newer model.
developers would not need to instantly buy new hardware to test 3D touch
Anybody knows if that is possible or knows code - please share with us.
You could perhaps emulate the behaviour by looking at the UITouch properties majorRadius and majorRadiusTolerance, available in iOS 8, which describe the approximate radius of the touch or "finger fatness".
This ought to be loosely correlated with pressure.
I'm not sure the properties change continuously / produce a stream of touchesMoved: callbacks, but it might be a start.
I have built a library to use as an alternative for devices without 3D Touch. My demo project also demonstrates how the project can support both types of devices. You can try it here: PeekView
The usage is pretty simple:
Add UILongPressGestureRecognizer to the view you want to peek (i.e
table view cell, image, hypertext, etc.)
Create a UIViewController
instance as the content of your peek view; then set your desired frame
for the content view. It's recommended to leave a 15px padding for
both left and right margin of your content view.
If you want to
include preview actions, prepare an array containing title of the
buttons and its preview style. Don't forget to prepare completion
handlers for when each button is tapped.
Sample snippet:
PeekView.viewForController(
parentViewController: self,
contentViewController: controller,
expectedContentViewFrame: frame,
fromGesture: gestureRecognizer,
shouldHideStatusBar: true,
withOptions: ["Option 1": .Destructive, "Option 2": .Default, "Option 3": .Selected],
completionHandler: { optionIndex in
switch optionIndex {
case 0:
print("Option 1 selected")
case 1:
print("Option 2 selected")
case 2:
print("Option 3 selected")
default:
break
}
})
Preview:
You can use this code to simulate peek and pop in the Simulator:
https://gist.github.com/nickfrey/07e2c6d8d2e5444fb91d
Adjust the time of the second dispatch_after between peek and pop.
Of course, this is only suitable for debugging since it uses private API.
This is what apple recommends:
"To ensure that all your users can access your app’s features, branch your code depending on whether 3D Touch is available. When it is available, take advantage of 3D Touch capabilities. When it is not available, provide alternatives such as by employing touch and hold, implemented with the UILongPressGestureRecognizer class."
Please check this link: https://goo.gl/4ez21g
Here’s an open source project that provides a neat tweak for the iPhone simulator that allows you to simulate 3D touch within the iOS simulator called SBShortcutMenuSimulator.
SBShortcutMenuSimulator allows you to test usage of the UIApplicationShortcutItem API even without a device supporting 3D touch.
This screenshot from the readme shows a demonstration of an application shortcut menu in the simulator:
STPopupPreview: https://github.com/kevin0571/STPopupPreview
An easy-integrate library for peak preview on non 3D Touch devices.
So I have created an App that has a different menu when it is held portrait, but changes when held landscape.
I can get the navigation to work, However I am unsure how to design landscape pages inside Flash?
My stage is set to the standard 640x960 air for iOS, which gives me perfect portrait pages, But when I tilt my phone to landscape the screen obviously changes, and it looks weird. Im hoping someone can tell me how i can get this view inside Flash, while still having the portrait screens too?
I want to have both Portrait and Landscape in the same app, and am currently so confused how I can design this inside flash?
I hope this makes sense, and that someone could throw some help my way!
It's not easy, but you can do it. First, you have to wait until stage is initialized and set it's scaling property to no scale (this will stop resizing page to fill screen). Then you have to listen to stage's resizing (it trigger's every time you rotate iPhone) and to move/scale your display objects in proper way in the listener handler.
addEventListener(Event.ADDED_TO_STAGE, init); //Wait for stage initialization
private function init(e:Event):void { //init handler
removeEventListener(Event.ADDED_TO_STAGE, init); //remove listener, which won't be used more
stage.scaleMode = StageScaleMode.NO_SCALE; //set null scaling and top-left align
stage.align = StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE, resize); //add handler for resizing
}
private function resize(e:Event):void { //triggers every time iPhone being rotated
//Move/scale your objects here
}
I want to know how to handle UI rotation. I have requirement to chang my UI layout when user rotates UI from Potrait to Landscape or vice versa. Let me know which event I need to handle and how do I get device height and width for both kind of rotation and adjust my UI.
I am also interested that if I use various layout then will it be adjusted automatically on UI rotation. Typical case is let say I have created UI using layouts which display two components on main screen, left side one list and right side content of particular item of list (this is same as explorer on windows). In this case if I rotate my UI then will it adjust correctly or I need to handle explicitly.
Please share your inputs on this asap.
Thank you very much in advance for your support.
Regards,
Premal Panchal
.
Marmalade handles Portrait to Landscape and vice-versa movement automatically, so You don't need to code it.
Register for the S3E_SURFACE_SCREENSIZE callback and then you can get notification when the screen size/orientation has changed:
s3eSurfaceRegister( S3E_SURFACE_SCREENSIZE, (s3eCallback)ScreenSizeOrientationChanged );
void ScreenSizeOrientationChanged( s3eSurfaceOrientation *orien, void *pUserData )
{
s3eDebugTracePrintf( "Orientation Changed: width=%d, height=%d, surfacewidth=%d, surfaceheight=%d, blitdirection=%s", orien->m_Width, orien->m_Height, Iw2DGetSurfaceWidth(), Iw2DGetSurfaceHeight(), S3E_SURFACE_BLIT_DIR_ROT180 ? "180" : "0" );
CGame *pGame = (CGame *)pUserData;
if( pGame )
{
pGame->ReCalculateScreenSize( orien->m_Width, orien->m_Height );
}
}
s3eSurfaceUnRegister( S3E_SURFACE_SCREENSIZE, (s3eCallback)ScreenSizeOrientationChanged );
You will notice that the GetSurfaceWidth/Height methods still report the original orientation values, so use the values passsed in the s3eSurfaceOrientation structure
Is anyone able to actually make it work properly in Flex SDK 4.6?
Here's a short snippet :
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
addedToStage="onAddedToStage(event)"
title="Title">
<fx:Script>
<![CDATA[
private function onAddedToStage(event:Event):void {
if (stage.autoOrients) {
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, false, 0, true);
}
}
private function orientationChanging(event:StageOrientationEvent):void {
if (event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN) {
event.preventDefault();
}
}
]]>
</fx:Script>
</s:View>
What I'm trying to achieve is to support Landscape mode in both orientations, so if user turns the device 180 degress, the screen should also rotate. But there should be no action at all, when user rotates the device to one of portrait orientations. Instead, I'm seeing width changes to navigator action bar and sometimes content in portrait orientations, so apparently preventing the event is not enough. I'm using the "official" way Adobe suggests, but the problem is that it's not working very well. Granted, the stage does not change, but it seems that there's something firing in navigator anyway, since you can see the action bar width changing.
I had some success with explicitly setting layoutbounds to fixed width in handler method - this prevents changing the actionbar width, but it's only a temporary solution - if the view is a subject to a transition, or some other redraw - it will again render with bad sizes. As if there was something below that was telling it that it's in portrait mode, even though I'm trying to prevent it.
Before you detonate with some silly ideas like "autoOrient = false", don't. It's clearly not a solution for this problem. Obviously it's a bug with Flex SDK - did anyone find a way to fix it or a stable workaround?
EDIT: apparently others bumped into similar issue:
- http://forums.adobe.com/message/3969531 (the main topic is about something else, but read magic robots's comment)
- http://forums.adobe.com/message/4130972
I'm not sure if this is the right one, did I do something wrong in the end, but after a lot of struggle, I've found this one to be stable solution:
private function onAddedToStage(event:Event):void {
if (stage.autoOrients) {
stage.removeEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging);
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, false, 100, true);
}
}
private function orientationChanging(event:StageOrientationEvent):void {
event.stopImmediatePropagation();
if (event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN) {
event.preventDefault();
}
}
First thing to note is that addedToStage fires few times (2-3) in mobile application. I don't know why, there's no addChild in my code, obviously. Maybe the AIR runtime does something else. So, to avoid adding unnecessary amount of handlers, the common technique is to remove handler first - it won't do anything, if such handler is not yet registered, but if there is, it will remove it, which will maintain the handler count on 1.
Second thing is the priority of the event - it won't work on 0, it has to be set on something big, to launch before stuff in AIR runtime.
Last thing - event.stopImmediatePropagation() - now, that we're the first to handle the event, we cant prevent this event to be sent further up in this particular scenario.
This together makes the orientation preventing working perfectly - for me the landscape and the reversed landscape (rotated_left, rotated_right) were working and transitioning, while portrait modes did not affect the view at all.
Now, there's danger here - you might want to remove the listener upon leaving the view (on transition animation end, view deactivate or something), because stopImmediatePropagation will prevent the event to be handled in other parts of your application.
I hope Adobe (or Apache now, actually) will take a closer look at this problem and trace my solution.
EDIT
There remaisn a last issue with this solution, which is if application starts while device is in DEFAULT or UPSIDE_DOWN orientation, in this case application will be in portrait mode.
To fix this, a solution is to change Aspect Ratio within addedToStage handler:
if(Stage.supportsOrientationChange) {
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
}
So I had the same problem you had. I think I finally figured out the solution. Heres what I did:
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
...blahblahblah...
width="1024"/>
protected function tabbedviewnavigatorapplication2_applicationCompleteHandler(event:FlexEvent):void {
stage.autoOrients=true;
preventOrient();
}
private function preventOrient():void {
if (stage.autoOrients) {
stage.removeEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging);
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, false, 100, true);
}
}
private function orientationChanging(event:StageOrientationEvent):void {
if(event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN || event.afterOrientation == StageOrientation.UNKNOWN) {
event.preventDefault();
}
}
Worth noting is that in the application complete handler I set stage.autoOrients to true because in the app.xml file I have it set to false, due to having a splash screen and not wanting users to re-orient the screen during that time. Really the only thing I did different is account for the StageOrientation.UNKNOWN and prevent whatever that would do, set the width to 1024(for the iPad screen, might be different for other tablet devices) in the main mxml file, and removed the stopimmediatepropagation. Hope this helps.