Problems with modal view launched over a split view controller - ios-simulator

I have created a split view application that begins with a modal view splash page. The problem is that the modal view always launches in portrait mode, even if the ipad is in landscape. If I rotate the ipad a couple of times, it rotates appropriately. I have set UIInterfaceOrientation in my Info.plist, but it doesn't have any impace.
in didFinishLaunchingWithOptions, I am using the following code
...
[self.window addSubview:splitViewController.view];
SplashViewController *modalView = [[SplashViewController alloc] intiWithNibName:nil bundle:nil];
modalView.modalPresentationStyle = UIModalPresentationFullScreen;
[splitViewController presentModalViewController:modalView animated:YES];
...
Any suggestions on how I can ensure the modal view launches in landscape?

I think this is the better way to do it:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight) {
return YES;
}
return NO;
}

I had a similar problem when using Matt Gemmell's MGSplitViewController. In my case, by trying to open a modal view controller in FormSheet mode from inside the detail view controller (that is the "right" pane in the UISplitViewController standard), my modal view was forcing interface rotation to portrait.
I found the solution by overriding the modal view controller -> shouldAutorotateToInterfaceOrientation: and letting him returning a NO:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return NO;
}
In this way when the modal is going to be presented, for some reason the OS tries to force it to portrait. By answering NO the view is no more rotated and everything works fine.

In the file from which you launch the modal view, you will want to change/override the following function. You can simply copy and paste the following code and you should be able to launch the modal view in portrait landscape mode:
- (BOOL)shouldAutoRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Good luck.
EDIT: I said portrait mode instead of what I meant: landscape mode.

Related

iOS 13 and UiSplitViewController when presenting in Portrait missing DisplayMode Button

I have the same issue as described here
UISplitViewController portrait mode missing UIBarButtonItem
my SplitView contains two NavigationControllers which each contains TableViewController
the Detail tableview controller is the split views delegate there all generated in code
and have a delegate method splitViewController:willChangeToDisplayMode:
and splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
for good measure
I have even tried to add the button my self if it is not there in splitViewController:willChangeToDisplayMode:
still no luck
any suggestions ?
Regards Christian
I Coded around the issue bu putting come code splitViewController:willChangeToDisplayMode: if the display mode is PrimaryHidden and the detail view controller don't contain a the splits view displauModeButtonItem in topmost navigationItem if the detail view controllers leftBarButtonsItems the I just manually add it
This is basically what #canderse said but I am showing the code. There is also a trick if you want your button to have a title. In your DetailViewController override the following method:
-(void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode{
//fix for missing navigation button
if(displayMode == UISplitViewControllerDisplayModePrimaryHidden){
self.navigationItem.leftItemsSupplementBackButton = true;
UIBarButtonItem *item=[svc displayModeButtonItem];
[self.navigationItem setLeftBarButtonItem:item animated:YES];
}}
For the button to have title, set your master view controller's title in awakeFromNib:
self.title = NSLocalizedString(#"Title", #"Title");
If you try to set the title in willChangeToDisplayMode, it won't work.

Android TV: Disable collapsing on info_field on ImageCardView

I'm working with Android TV for the first time and I'm learning to use Leanback by modifying the example tv app that is provided.
The issue I'm having is that when I press left on the first item in the lists the navigation drawer opens and focus goes to the headers in the navigation drawer. When this happens, the info_field view in the ImageCardViews collapse behind the image.
What happens: The info field on the ImageCardView hides when I open the navigation drawer.
What I want to Happen: The info field remains visible when I open the navigation drawer.
I'm sure there's a way to do this because I've seen it in some Android TV apps, like Twitch. What's the best way to have the info_field visible when the navigation drawer is open?
I've worked out how to do it. In the CardPresenter, in onCreateViewHolder, when creating the ImageCardView I've overridden the BaseCardView method, setActivated(boolean activated) to always pass 'true' into it's super. And then call setActivated so that it's activated from the beginning. Like this:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
ImageCardView cardView = new ImageCardView(parent.getContext()) {
#Override
public void setActivated(boolean activated) {
super.setActivated(true);
}
#Override
public void setSelected(boolean selected) {
updateCardBackgroundColor(this, selected);
super.setSelected(selected);
}
};
cardView.setActivated(true);
cardView.setFocusable(true);
cardView.setFocusableInTouchMode(true);
return new ViewHolder(cardView)
}
So that did the trick for me. The ImageCardView never collapses.
I think if you look at this SO post you'll get most of the way there. The info view hides due to what leanback calls "expanding".
Try just calling enableMainFragmentScaling(false); in your BrowseFragment and see if that does what you want. If it doesn't feel like exactly what you want, refer to the post I linked to.
Additionally, if you've tried what I recommend in the linked SO post, you could also call the API on the BaseCardView setInfoVisibility() and pass it CARD_REGION_VISIBLE_ALWAYS. This just requires calling on a reference to your card which shouldn't need an override of the Presenter or Card.

How to make UIsplitview's popover visible in portrait mode iPad

I would like to make popover view visible whenever user switches from landscape view to portrait view in UIsplitView of iPad. Although user can make it visible by clicking on bar button but I want this to be automated for portrait mode.
Inside " -(BOOL) shouldAutorotateToInterfaceOrientation" method, check for the device orientation.If it is portrait, then Present the popover as you do for making it visible when user clicks bar button.
All the best.
UISplitViewController sends messages to his delegate (UISplitViewControllerDelegate). You can implement this delegate methods to show the popover. You can do something like this in your "detail controller" code:
#pragma mark -
#pragma mark UISplitViewControllerDelegate implementation
- (void)splitViewController:(UISplitViewController*)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem*)barButtonItem
forPopoverController:(UIPopoverController*)pc
{
[barButtonItem setTitle:#"Your 'popover button' title"];
self.navigationItem.leftBarButtonItem = barButtonItem;
}
- (void)splitViewController:(UISplitViewController*)svc
willShowViewController:(UIViewController *)aViewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
self.navigationItem.leftBarButtonItem = nil;
}
The accepted answer (using shouldAutorotateToInterfaceOrientation) doesn't work for me. It either has rotation artifacts (in the 4.2 and 5.0 iPad simulators) or only shows at startup and never again in subsequent rotations (the 4.3 simulator). What I did instead was to create a little helper function:
- (void)showPopoverInPortrait {
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait) {
[self.masterPopoverController presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
and call this within - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation and - (void)viewDidLoad to also handle on startup.

UISplitviewcontroller not as a rootview controller

I am building my first iPad application. And one of my requirements is to deal with UISplitviewcontroller and UINavigationController.our proposed view hierarchy is (LoginView) ->UINavigationView(LandingView + CollectionView)->UISplitViewcontroller( DetailsView).Our app supports only landscape mode
I am referring this SO Question( and GILT app as well), as a newbi its hard for me to get it done based on that description.
So my questions are
1) How can I achieve same thing,if somebody can give small code snippets or reference to tutorial
2) As per Apples HIG, UISplitviewcontroller should be rootviewcontroller,what if it not. Will apple reject my app.(apparently GILT group has been approved)
3) I found MGSplitViewController , can I use that one not as root?
Any help would be appreciated. As a newbi i hope my question is genuine
If you want to use the out-of the box splitView it must be root; any hokeary-pokery here will either break apples guidelines or manifest very odd behaviour.
The MGSplitViewController is completely custom implementation of a SplitViewController. Its very good if you need that sort of thing, but some of the features are based round the fact that our app will be orientating.
Alternatively you could make your own. I have done this more than once and is easier than it sounds.
(LoginView)
->UINavigationView(LandingView + CollectionView)->UISplitViewcontroller(
DetailsView).
Based on an out-of-the-box UISplitView, I would suggest:
Make the splitView the root View.
Pop (not animated) a full screen Modal as soon as the app starts and allow the
user to navigate the loginView,
LandingView and collectView in this; i also recommend using a navController here.
Once the user is ready to proceed to
the splitView, populate the
splitView's rootView Controller and
DetailViewController with whatever
you want then ,animate the Modal out.
Dave does have a point, but i would look at it from the point of view that you are removing the choice of orientation from the user; removing standard choices (like supported orientations) because the designer assumes some configuration is more efficient will only annoy some users.
I did it by making a method in my detailViewController:
-(void)popHomeScreen:(BOOL)animated//OPENS THE HOMESCREEN IN A MODAL DISPLAY
{
firstRun=NO;
//myViewControllerForPopOver init here
myViewControllerForPopOver.modalPresentationStyle = UIModalPresentationFullScreen;
myViewControllerForPopOver.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;//simple anime
if (animated) [self presentModalViewController:myViewControllerForPopOver animated:YES];
else [self presentModalViewController:myViewControllerForPopOver animated:NO];
}
Then Call it in the detailViewControllers ViewDidAppear method:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(firstRun)[self popHomeScreen:NO];
}
//YOU WILL ALSO NEED TO MAKE 'firstRun=YES' in viewDidLoad
//firstRun is a BOOL
As for the root disappearing (leaving a big black space)..thats a known bug. though i thought for a while that it was caused by ordering an animation while/just before it was going to draw itself.
Also, i found that if i popped a full screen modal over the splitView then popped another form based modal (for example) quickly after it the full screen modal didn't draw properly.
SplitViews are like your mother-in-law, you don't really like them and when you have to use them you have to tip-toe round the landmines.
Try this, it works for me
1) in app delegate's didFinishLaunchingWithOptions make your login view to root view
self.window.rootViewController = self.loginViewController;
also, init the split view as the template do ( but not add to self.window)
MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil] autorelease];
UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
self.splitViewController = [[[UISplitViewController alloc] init] autorelease];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController ,detailNavigationController, nil];
2) add a swap view controller in app's delegate, which swap the root view to split viewcontroller.
-(void)swapToViewControllers:(RootViewControllerType)viewType
self.window.rootViewController = self.splitViewController;
3) invoke the swapToViewControllers in your login view.
Keep in mind that the HIG strongly encourages you to support all orientations. Unless you have a very, very good reason to support landscape only, you'll probably be rejected.
See page 19 of the HIG: http://developer.apple.com/library/ios/documentation/General/Conceptual/iPadHIG/iPadHIG.pdf
Modified Ryan CY's version with storyboard.
Put this code to login controller.
1. Set storyboard id of UISplitViewController to SplitViewController;
2. Set UISplitViewController delegate and save instance
UISplitViewController* splitController = [self.storyboard instantiateViewControllerWithIdentifier:#"SplitViewController"];
UINavigationController* navigationController = [splitController.viewControllers lastObject];
splitController.delegate = (id)navigationController.topViewController;
3. Change rootViewController after login
self.view.window.rootViewController = splitController;

Limiting landscape views in UITabBarController containing UINavigationController

I have a tab bar application that contains navigation views in 2 of its tabs. I would like 1 view in the 1 navigation controller to allow landscape view but because of the nav bar in tab bar limitation I now have to allow landscape views for every single view in my app to make the tilt messages get passed to my app which I don't want.
I thought perhaps, on the views which shouldn't go to landscape, that there might be ways to either:
prevent the view change e.g. calling setOrientation:UIDeviceOrientationPortrait whenever the device goes landscape
or
giving the illusion that the view doesn't change e.g. presenting a modal portrait view over the rotated view
Anybody have any ideas or experience that they care to share? What is the best approach here? (I don't want to now have to design a landscape view for every view just to so that I can display a portrait & landscape view for 1 view)
I had to deal with the same problem recently and my solution is as follows:
within the UIViewController of the View that you want to be able to rotate add a Notification Handler for the UIDeviceOrientationDidChangeNotification
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotateFromInterfaceOrientation)
name:#"UIDeviceOrientationDidChangeNotification" object:nil];
}
then of course you need to implement your didRotateFromInterfaceOrientation Method.
within that Method you can get the current orientation using
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
what I did next was evaluation the view i want to display, based on the orientation
switch (orientation) {
case UIDeviceOrientationLandscapeLeft:
NSLog(#"UIDeviceOrientationLandscapeLeft");
[self presentModalViewController:LandscapeView animated:YES];
break;
case UIDeviceOrientationLandscapeRight:
NSLog(#"UIDeviceOrientationLandscapeRight");
[self presentModalViewController:LandscapeView animated:YES];
break;
case UIDeviceOrientationPortraitUpsideDown:
NSLog(#"UIDeviceOrientationPortraitUpsideDown");
[LandScapeview dismissModalViewControllerAnimated:YES];
break;
case UIDeviceOrientationPortrait:
NSLog(#"UIDeviceOrientationPortrait");
[LandscapeView dismissModalViewControllerAnimated:YES];
break;
case UIDeviceOrientationFaceUp:
NSLog(#"UIDeviceOrientationFaceUp");
break;
case UIDeviceOrientationFaceDown:
NSLog(#"UIDeviceOrientationFaceDown");
break;
default:
break;
}
}
I hope i could help a bit.

Resources