How to set an iOS app for iPad to fullscreen programmatically?
Are you talking about the status bar which is visible? In the info.plist for your app, you can add a new entry, UIStatusBarHidden and make sure its checked. This would ensure that the status bar is hidden. You also have to make sure that your views are able to handle the additional screen real estate also.
Nowadays (since IOS7) in order to do this you need to override a small tiny lily method of each UIViewController you want to do this
Swift
override func prefersStatusBarHidden() -> Bool {
return true;
}
Objective C
-(BOOL)prefersStatusBarHidden{
return YES;
}
Apple Doc:
Maybe you want this one:
[self setWantsFullScreenLayout:YES];
just add it at your viewController's init method.
Someone else may need it. ;)
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
(other animation modes are ...Fade and ...Slide.)
You need to override var rather func,
override var prefersStatusBarHidden: Bool {
return true
}
Related
I want to know how to disable/enable rotation during view life.
Is there a way to update shouldAutorotate in the view life(without reloading the view)
Thanks.
From the Apple Docs :
shouldAutorotate
Returns a Boolean value indicating whether the view controller's contents should auto rotate.
Declaration
SWIFT
func shouldAutorotate() -> Bool
OBJECTIVE-C
- (BOOL)shouldAutorotate
More on this : https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/shouldAutorotate
You should add this to the method where you decide if the user can rotate or not of your ViewController :
override func shouldAutorotate() -> Bool {
return false
}
See also : Setting device orientation in Swift iOS
I am facing problem in view orientation in my app.
Like
I have two view controller, VC1 and VC2
VC1 have fix landscape orientation.
VC2 have both
VC1 -> VC2 is fine. means when I go from VC1 to VC2, VC2 change its orientation in both landscape and portrait.
But when I comeback to VC1 from VC2(where VC2 in portrait mode), VC1 also is in portrait mode but I want VC1 is in landscape only irrespective of VC2 mode.
Please guys help me. Seeking solution from last 2 days.
Thanks in advance.
Refer below link for solution
http://swiftiostutorials.com/ios-orientations-landscape-orientation-one-view-controller/
In your VC1..
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
Hope it helps you...
First of all, write this in AppDelegate.m
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return (UIInterfaceOrientationMaskAll);
}
Then, For VC1, in which landscape orientation, write this:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait);
}
For VC2, which have both, change masking to All.
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskAllButUpsideDown);
//OR return (UIInterfaceOrientationMaskAll);
}
1. Enable all orientation support for project.
For VC1 Add this line VC1Controller Class
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
For VC2 Add this in VC2Controller Class
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
basically the view-controller-based orientation support in an iOS app is a piece of cake – I did the code in Swift, but ObjC concept would be totally identical to this.
I have created a quick tutorial with UINavigationController but you can convert that to UITabBarController by keeping the concept but updating the environment slightly.
step-1
initially set the orientation support for your app like this:
step-2
create a simple UINavigationController-based storyboard like this:
NOTE: don't worry if it does not say initially OrientaionSupporterController (bonus point if you'd spot the consistent typo here!), I will cover that just in the very next step.
step-3
create a subset of the navigation-controller, like this:
import UIKit
// MARK: - Implementation
class OrientaionSupporterController: UINavigationController {
// MARK: - Active View Controller
private var activeViewController: UIViewController? {
get {
return self.presentedViewController ?? self.topViewController // for possible modal support
}
}
// MARK: - Orientations
override var shouldAutorotate: Bool {
get {
return self.activeViewController?.shouldAutorotate ?? true // yes, rotate it, please
}
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return self.activeViewController?.supportedInterfaceOrientations ?? .all // default is all possible orientations
}
}
then make sure the that becomes the base class in IB as well:
step-3
create the individual view-controllers with custom orientation support, like e.g. with only portrait and landscape-left support:
import UIKit
// MARK: - Implementation
class ViewController: UIViewController {
// MARK: - Orientation
override var shouldAutorotate: Bool {
get {
return true
}
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait, .landscapeLeft] // no one find that preactical but works flawlessly
}
}
NOTE: you can convert this tutorial anytime with UITabBarController, you just need to (obviously) create a subset of the tab-bar-controller and use the selectedViewController to get the currently visible one.
NOTE#2: obviously you can go much further on this way and you can nest the customised navigation-controllers in the view hierarchy, or if you have multiple UIWindow instances in the queue and override the supported orientations there as well for each individual windows (e.g. some support all four orientations, while some other windows does only landscape for e.g. video playback, etc...)
I am adding an MPMoviePlayerViewController to my app like this:
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];;
[self presentMoviePlayerViewControllerAnimated:vc];
Everything is working but I can't enable landscape mode. I want my whole app except the actual MPMoviePlayerViewController to be portrait. I searched on google but all the solutions require having the rest of the app also in landscape.I need my app to stay in Portrait except in the MPMoviePlayerViewController.
Thanks in advance!
EDIT:
Using #matt answer I added landscape to my Device Orientation:
Next I went to my First View Controller(Not the MPMoviePlayerViewController) and added:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
However the app still let's the Main Menu go to Landscape mode.
Actually there is a way to just make Movie Player landscape without affecting portrait view of rest of screens.
#define degreesToRadian(x) (M_PI * (x) / 180.0)
MPMoviePlayerViewController *moviePlayerVC = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:#"http://someurl.com"]];
moviePlayerVC.view.transform = CGAffineTransformIdentity;
moviePlayerVC.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
[self presentViewController:moviePlayerVC animated:NO completion:NULL];
Make sure you are using MPMoviePlayerViewController and not MPMoviePlayerController, else it won't work.
The problem is that MPMoviePlayerViewController is not your class so you have no control over its response to supportedInterfaceOrientations, which is what you would use to dictate the orientation of the presented view if this were your own view controller class. So you must make it your own view controller class. You will have to create your own MPMoviePlayerViewController subclass so that you can override supportedInterfaceOrientations and express what orientation you want (i.e. landscape). Create and present an instance of that subclass, not the built-in superclass.
For Xcode 6.4, Swift 1.2 edited #Chandresh Panchasara answer a bit.
let movieC = MPMoviePlayerViewController()
movieC.moviePlayer.contentURL = self.movieURL
movieC.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
movieC.view.transform = CGAffineTransformIdentity;
movieC.view.transform = CGAffineTransformMakeRotation(CGFloat((M_PI * (90.0) / 180.0)));
self.view.window?.rootViewController?.addChildViewController(self)
self.presentMoviePlayerViewControllerAnimated(movieC)
Thanks for you answers it helped me.
For those who want it for Swift 4 here the solution:
playerVC.view.transform = CGAffineTransform.identity
playerVC.view.transform = CGAffineTransform.init(rotationAngle: degreesToRadian(90.0))
present(strongPlayerVC, animated: true)
Here the function degreesToRadian:
func degreesToRadian(_ degrees: CGFloat) -> CGFloat {
return .pi * degrees / 180.0
}
Thanks and good luck!
The best way so far is to implement this AppDelegate function and check if the rootViewController has a child of type AVPlayerViewController then you return [.portrait, .landscapeLeft, .landscapeRight] and else .portrait.
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let _ = UIApplication.shared.keyWindow?.rootViewController?.childViewControllers.first as? AVPlayerViewController {
return [.portrait, .landscapeLeft, .landscapeRight]
}
return .portrait
}
You should check on the keyWindow of UIApplication because apple presents this viewController in a another UIWindow so if you try to do that check on the window that is declared in the AppDelegate this won't work so be careful.
I came across a strange bug in my app:
The setup
A simple Master-Detail app, iPhone style (ie. no split view, no popover, just a navigation controller, a table view controller, and a view controller).
The bug
Touch a "background" part of the table view (the darker grey parts on my screenshot) like a section header or footer.
While keeping your finger on the screen, touch a cell multiple times.
Release all fingers. The "detail" view will pushed normally, but when touching the back button, you will find that the detail view was stacked as many times as you touched the cell at step 2.
You can also touch multiple cells at step 2 and their destination views will be stacked in the correct order :)
Reproduce it
I was able to reproduce the bug with a clean, freshly created app, and on the last release of the Twitter app for iPhone (by touching the "Loading" label with finger #1 and touching a tweet multiple times).
However, I could not trigger the same behaviour in the Settings app, under the "General" tab (which is a grouped table view).
The bug was reproduced on iOS 6.0 and 6.1. I don't have devices with older versions to test.
Question
Is this a known trick when creating navigation/table view based apps and if so is there a solution to prevent this (weird) behavior ? Or is this an iOS bug (and if so, is it already known from Apple) ?
A possible stop-gap measure you could use is to implement
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
And use a boolean flag or something to indicate that you are currently trying to execute that segue. ex:
BOOL doingSegue = NO;
-(void) viewWillAppear
{
doingSegue = NO;
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ( [identifier isEqualToString:#"MySegueIdentifier"] )
{
if ( doingSegue )
{
return NO;
}
else
{
doingSegue = YES;
return YES;
}
}
return YES;
}
Swift Version
var doingSegue = false
override func viewWillAppear(_ animated: Bool) {
doingSegue = false
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "MySegueIdentifier" {
if doingSegue {
return false
}
else {
doingSegue = true
return true
}
}
return true
}
This is fixed by Apple in iOS 7.
For prior versions of the OS, Dan F's answer should do the trick.
I am running into an issue where the keyboard does not get dismissed when leaving a UITextField or UITextView in a UIModalPresentationFormSheet. In addition, I've created a large button to serve as the view's background so if the user taps outside the fields it gets triggered. I am using the same code in a regular view controller, and it works as expected. In the modal view controller it does nothing. Any suggestions would be appreciated.
- (BOOL)textFieldShouldReturn:(id)sender {
[titleTextField resignFirstResponder];
return YES;
}
- (BOOL)textViewShouldReturn:(id)sender {
[synopsisTextView resignFirstResponder];
return YES;
}
- (IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)textViewDoneEditing:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)backgroundClick:(id)sender {
[titleTextField resignFirstResponder];
[synopsisTextView resignFirstResponder];
}
Overriding disablesAutomaticKeyboardDismissal to return NO as below fixed the same problem of mine. You should put this code to your view controller, from which you initiate the keyboard:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
Also, check this SO question if you want to get a detailed explanation.
For those having trouble with UINavigationController, I think there is a better solution than a category on UIViewController. We should change the behavior of UINavigationController to ask its topViewController (in my opinion, this is how all ViewController containers should handle this).
#implementation UINavigationController (DelegateAutomaticDismissKeyboard)
- (BOOL)disablesAutomaticKeyboardDismissal {
return [self.topViewController disablesAutomaticKeyboardDismissal];
}
If you're presenting a modal view with presentation style "form sheet", Apple apparently does not dismiss the keyboard, thinking that they don't want the keyboard to jump in and out where a user will be doing a lot of editing (i.e. "forms"). The fix would be to change presentation style or live with it.
If you implement the UITextFieldDelegate protocol you can inadvertently cause this behavior if you do text validation. If your validation codes returns false from textFieldShouldEndEditing when the text is invalid, the field can't relinquish it's firstResponder status and the keyboard will remain on screen in the next view.
More details at UITextField's keyboard won't dismiss. No, really
I solved this by resizing a UIModalPresentationPageSheet. See my answer here.
The disablesAutomaticKeyboardDismissal refused to work for me on iOS 7.
But... I managed to solve this issue by simply disabling the UITextFields on the screen.
My solution is described here.
This workaround even works on Modal UIViewControllers.
Yeah... it surprised me aswell !!
i have also facing same problem and also done everything but not thing works then i start thinking and get some result.
but this answer for those who want to dismiss keyboard on textfield click and then open pop up.
so all you need to call text field delegate
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == self.myTxtFieldName{
self.view.endEditing(true) // keyboard hide code
// here you can call your model or pop up code and keyboard will dismiss and your pop up open
return false
}
return true
}
Sorry if this is not working for you
if there is other answer then please edit it
Thank you