I have a setup where an iPad app supports all orientations. In part of the application, a tap triggers the display of a modal view controller which requires a navigation controller. So I'm basically doing:
UIViewController *myViewController = [[UIViewController alloc] initWithNibName:#"MyView" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:myViewController];
NSLog(#"%d", nav.interfaceOrientation);
[window.rootViewController presentModalViewController:nav animated:YES];
This works fine when the iPad is in portrait (home button). In any other orientation, the modal view always appears in portrait from the home button rather than the current bottom of the device.
If I skip the navigation controller completely and just show myViewController modally, it appears correctly.
So, I tried subclassing the UINavigationViewController and explicitly overriding the shouldAutorotate: and supportedInterfaceOrientations: methods, but this doesn't have any effect. Interestingly if I override the viewWillAppear method and log the value of the interfaceOrientation property, this always returns 1 even if it returns the correct value when accessing it from the code above.
I've also checked that all orientations are supported in Info.plist.
So, what else could be happening to cause this behaviour? Any help greatly appreciated.
Try to implement preferredInterfaceOrientationForPresentation in your subclass of the navigation controller.
The following worked for me:
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return self.interfaceOrientation;
}
Related
I'm working on a mapping app using ionic and leaflet. Note that I am not using the leaflet angular directive, I am using straight JS for the leaflet map (I know, I know...).
The initial state in my app loads the leaflet map just fine. If I switch to another state and back to the map everything is also fine. However, if I launch the app, switch to a different state and open a modal window in that state, then return to the original state, the map is broken and displays a number of grey tiles. The map will not update until the browser window resizes or the orientation of the mobile device is changed.
Here's a demo on Plunker: http://plnkr.co/edit/w67K2b?p=preview. To reproduce:
Click the button at the right side of the navbar which will take you to a different state.
Click the 'Back to map' button to go back to the original state. The map looks just fine.
Click the button in the navbar again.
Click the 'Open modal' button and then close the modal.
Click the 'Back to map' button and you will see that the map is now broken.
I've seen other people report issues with grey tiles, which typically can be resolved with a call to:
map.invalidateSize()
Unfortunately this does not resolve my issue. I'm pretty much a newb, but I think the problem is that when the modal opens, the invalidateSize() method in the leaflet source code is run, since the map div is not visible, the 'size' gets set to x:0, y:0 which ends up breaking the map when I transition back to the original state.
I'm not really sure where to go from here. Perhaps I can use JS to dynamically resize the div and trick leaflet into thinking a resize event has occurred? How would I do this? Any other thoughts?
Thanks!
I have an amchart in a div whose show/hide is managed by angularjs. Sometimes it charts data that's already in memory. When that is the case, the div opens, chart is rendered and the SVG in there has a width of 10. As a result the chart does not appear on screen. Resize the window a mite and the chart appears because amcharts is listening to resize events I guess. This I think is a known issue - I have seen some SO posts on them and I hope one of them will work for me. My suspicion is that the angular machine does not get cycles to run open the div before amcharts gets to draw its magic (just a hunch no solid evidence.)
Next, I added an event watcher
piechart.write(divs.chart_div.attr('id'));
divs.chart_div.on('yes', 'snowy', function(){ // same with 'shown','resize'
console.info('============= woah ========');
});
Now a strange thing happened. I see the following error stack in my console
Error: [jqLite:onargs] jqLite#on() does not support the `selector` or `eventData` parameters http://errors.angularjs.org/1.3.13/jqLite/onargs
at REGEX_STRING_REGEXP (http://localhost:8100/lib/ionic/js/ionic.bundle.js:8762:12)
at jqLiteOn (http://localhost:8100/lib/ionic/js/ionic.bundle.js:11733:39)
at Object.JQLite.(anonymous function) (http://localhost:8100/lib/ionic/js/ionic.bundle.js:11951:17)
at Object.makePieChart (http://localhost:8100/common/services/graphinghelperService.js:528:34)
at obj.controller.$scope.myExt.renderFunc (http://localhost:8100/directives/boxRenderers2.js:179:24)
at _render_it (http://localhost:8100/modules/dashboard/dashboard.js:246:30)
at $scope.showBox.deferred.promise.then.workarea.showChild (http://localhost:8100/modules/dashboard/dashboard.js:310:17)
at processQueue (http://localhost:8100/lib/ionic/js/ionic.bundle.js:21888:27)
at http://localhost:8100/lib/ionic/js/ionic.bundle.js:21904:27
at Scope.$get.Scope.$eval (http://localhost:8100/lib/ionic/js/ionic.bundle.js:23100:28)
And that funky behavior is gone ! The chart appears if I click to redraw it out of cached data, hides when click again, and all good. No more bland background colored div to stare at!!.
However, if I change the watch to divs.chart_div.on('shown', function(){ then the event handler is not called and the chart does not appear when rendered out of cached data.
I wonder what's going on.
Looks like something (might be the armchart library?) is expecting jQuery to be available to bind to an event. Angular comes with jqLite, a stripped down version of jQuery so that's why you're getting that exception.
I'm guessing it's something here on this line.
at Object.makePieChart (http://localhost:8100/common/services/graphinghelperService.js:528:34)
Use the full version of jQuery instead to take care of that problem: http://www.bennadel.com/blog/2752-using-jquery-instead-of-jqlite-in-angularjs.htm
so I created my own custom layouts for my UICollectionView. When i rotate from portrait to landscape mode, some of the cells start to reload its content. I thought the layout just changes the positions of every cell not reload the content?
The content should only reload when i call reload Data on the collection view.
Any ideas to what might be going on?
Use invalidateLayout instead of reloadData on rotation, or override shouldInvalidateLayoutForBoundsChange: and return YES in your UICollectionViewLayout subclass.
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
myCollectionView.frame = self.view.bounds;
[myCollectionView.collectionViewLayout invalidateLayout];
}
Not sure if you are aiming for this, but here it goes:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.collectionView reloadData];
}
Does anybody has an idea about how could I dismiss a popover before orientation change on iOS 6.
I've tried the following:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:NO];
}
}
But it is not working for me. The popover is still there after the rotation.
- (BOOL) shouldAutoRotate
is not called in my viewController cause it's in a SplitViewController and NavController.
I've read that I can subclass from this containers to forward the shouldAutorotate, but I don't want to do this because of different reasons.
I don't want to dismiss popover after orientationchange (in didRotateFrom...), because it's ugly.
Do you have an idea, how could I dismiss the popover before orientation change on iOS 6?
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deviceOrientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
This will do it once the rotation did change then you can do what you want in the device orientation. Otherwise you need to listen on the view controllers and send the message there.
try this
- (void)viewDidLayoutSubviews
{
[popOverController dismissPopoverAnimated:YES];
}
I want to display a modal view but I have two problems:
There is no presentModalViewController in iOS 6 and I have to use presentViewController which is just display my second ViewController like a modal segue not a modal window without full screen option,
My second problem is how can I show the modal window from UICollectionViewController. I tried to use presentViewController but it just works with ViewController not CollectionViewController.
The best example of what I want to do is this (Instagram). How they made this modal window? Is it because it's still working with older iOS versions and it's not iOS 6 yet? Or there is another way to display modal window like this from UICollectionViewController?
Thanks
If I understood you correctly what you are trying to achieve is to present one of your ViewControllers over the parent and still see the parent ViewController in the background.
First solution:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.view.backgroundColor = [UIColor clearColor];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext; //self.modalPresentationStyle might do a better job here
[self presentViewController:vc animated:NO completion:nil];
Make sure your SecondViewController content is smaller than your current ``ViewController` and that you can see the background color of it in StoryBoard \ xib. The background color will be clear and will create the transparency effect.
Second Solution:
Create a Container (iOS 6 and up if you are planning to use the Storyboard IB, lower than that will let you create Containers but only progrematicly).
Set the container size 3/4 of the parent size and connect the second viewcontroller to it. Instead of segueing \ pushing to your second viewcontroller you can just
myContainer.alpha = 1;
to show it on screen.
I would take a look at the docs for UIContainerView which is used for displaying a view controller as a child of another view controller in a similar way to a non-fullscreen modal presentation.
As you are saying that presentViewController is only works with UIViewController not UICollectionViewController.
Then simply import UIViewController class in header file of CollectionViewController as displayed below:
#import <UIKit/UIKit.h>
#class UIViewController;
#interface MyCVController : UICollectionViewController
#end