Popover with ModalPresentationStyle is not centered in iOS 7 iPad

前端 未结 6 1365
悲哀的现实
悲哀的现实 2021-01-31 19:18

I have a problem with iOS 7 that seems to be a bug or I just don\'t do something right. I have modalViewController that appears as a popover on iPad with ModalPresentationStyle.

相关标签:
6条回答
  • 2021-01-31 19:31

    I had the same problem. I have solved this by using another approach, found here.

    What this solution proposes is to use the method (void)viewWillLayoutSubviews

    So in case of @Manuel M. inside the GeneralSettingsViewController add the code below:

    // GeneralSettingsViewController
    - (void)viewWillLayoutSubviews{
        [super viewWillLayoutSubviews];
        self.view.superview.bounds = CGRectMake(0, 0, 497, 375);
    }
    

    And you won't need this code anymore:

    self.generalSettingsVC.view.superview.frame = CGRectMake(0, 0, 497, 375);
    self.generalSettingsVC.view.superview.center = self.view.center;
    

    For @titicaca, you are using a UINavigationController I haven't test it with this Controller but you could try the same solution I mentioned, extending the UINavigationController and overwrite the viewWillLayoutSubviews method.

    [EDIT]

    For @titicaca I tried it in a new project and for me it worked. What I did was having a custom navigation view controller CustomNavigationController overriding the viewWillLayoutSubviewslike this:

    - (void)viewWillLayoutSubviews{
        [super viewWillLayoutSubviews];
        self.view.superview.bounds = CGRectMake(0, 0, 330, 284);
    }
    

    Then, the view controller that presents the CustomNavigationController should execute a code similar to this:

    UIViewController *myVC = [[UIViewController alloc] init];
    [myVC.view setBackgroundColor:[UIColor redColor]];
    
    CustomNavigationController *nav = [[CustomNavigationController alloc] initWithRootViewController:myVC];
    [nav setModalPresentationStyle:UIModalPresentationFormSheet];
    [nav setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
    
    [self presentViewController:nav animated:YES completion:nil];
    

    You need to make sure though, that the dimensions of the self.view.superview.bounds = CGRectMake(0, 0, 330, 284); are even numbers otherwise the text inside gets fuzzy, if there is any

    0 讨论(0)
  • 2021-01-31 19:35

    I have a method where the old custom modal presentation style fromsheet works with iOS <=7 although you might set custom height and width.

    Keep in mind that this method might not work in any newer version in the future

    - (void) hackModalSheetSize:(CGSize) aSize ofVC:(UIViewController *) aController;
    {
    
        void (^formSheetBlock) (void) = ^{
            int preferredWidth = aSize.width;
            int preferredHeight = aSize.height;
    
            CGRect frame = CGRectMake((int) 1024/2 - preferredWidth/2,
                                      (int) 768/2 - preferredHeight/2,
                                      preferredWidth, preferredHeight);
            aController.view.superview.frame = frame;
            if([aController respondsToSelector:@selector(edgesForExtendedLayout)]) { //ios7
                aController.view.superview.backgroundColor = [UIColor clearColor];
            } else { // < ios7
                UIImageView *backgroundView = [aController.view.superview.subviews objectAtIndex:0];
                [backgroundView removeFromSuperview];
            }
        };
    
        //on ios < 7 the animation would be not as smooth as on the older versions so do it immediately
        if(![self respondsToSelector:@selector(edgesForExtendedLayout)]) {
            formSheetBlock();
            return;
        }
    
        double delayInSeconds = .05;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            formSheetBlock();
        });
    }
    
    0 讨论(0)
  • 2021-01-31 19:35

    For me the issue was calling becomeFirstResponder on a text field in the viewDidAppear of the presented view controller. Appears to be a bug with that now. The solution was wrapping it in a simple dispatch_async:

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.userNameTextField becomeFirstResponder];
        });
    }
    
    0 讨论(0)
  • 2021-01-31 19:35

    I went about this slightly differently using a subclassed navigation controller and AutoLayout in Swift, to center the view in the superview at a set width and height. My particular case needed iPad and iOS7-8 support (there's some constants specific to my project in this code, but you get the idea) ...

    class CenteredModalNavigationController: UINavigationController {
    
        // MARK:- Methods
    
        override func viewDidLoad() {
            super.viewDidLoad()
            preferredContentSize = CGSizeMake(320, 480) // iOS8 only
        }
    
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
    
            // iOS7 support for iPad custom sized form-sheet modal.
            if kDeviceiOS7 && kDeviceiPad {
                if view.superview == nil {
                    Log.warning("Failed to find superview")
                    return
                }
                view.superview!.setTranslatesAutoresizingMaskIntoConstraints(false)
    
                // Give the superview constraints to center the view inside it.
                var viewBindingsDict: NSMutableDictionary = NSMutableDictionary()
                viewBindingsDict.setValue(view, forKey: "view")
                viewBindingsDict.setValue(view.superview!, forKey: "superview")
                let centerXConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:[superview]-(<=1)-[view]",
                    options: .AlignAllCenterX,
                    metrics: nil,
                    views: viewBindingsDict)
                view.superview!.addConstraints(centerXConstraints)
    
                let centerYConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:[superview]-(<=1)-[view]",
                    options: .AlignAllCenterY,
                    metrics: nil,
                    views: viewBindingsDict)
                view.superview!.addConstraints(centerYConstraints)
    
                // Now give it a width/height and it should float in the middle of our superview.
                AutoLayoutHelper.addWidthConstraint(view,
                    aSuperView: view.superview!,
                    width: 320)
                AutoLayoutHelper.addHeightConstraint(view,
                    aSuperView: view.superview!,
                    height: 480)
            }
        }
    
        override func prefersStatusBarHidden() -> Bool {
            return true
        }
    
        override func disablesAutomaticKeyboardDismissal() -> Bool {
            // DEVNOTE: Because this is shown in a modal, this is required to stop keyboard dismiss issues.
            return true
        }
    
    }
    

    ...

    class AutoLayoutHelper: NSObject {
    
        class func addHeightConstraint(aChildView:UIView, aSuperView:UIView, height:CGFloat) {
            var constraint = NSLayoutConstraint(item: aChildView,
                attribute: NSLayoutAttribute.Height,
                relatedBy: NSLayoutRelation.Equal,
                toItem: nil,
                attribute: NSLayoutAttribute.NotAnAttribute,
                multiplier: 1.0,
                constant: height)
            aSuperView.addConstraint(constraint)
        }
    
        class func addWidthConstraint(aChildView:UIView, aSuperView:UIView, width:CGFloat) {
            var constraint = NSLayoutConstraint(item: aChildView,
                attribute: NSLayoutAttribute.Width,
                relatedBy: NSLayoutRelation.Equal,
                toItem: nil,
                attribute: NSLayoutAttribute.NotAnAttribute,
                multiplier: 1.0,
                constant: width)
            aSuperView.addConstraint(constraint)
        }
    
    }
    
    0 讨论(0)
  • 2021-01-31 19:36

    The solution above did not work for me. I used the following:

          UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:theViewController];
          navigationController.modalPresentationStyle=UIModalPresentationFormSheet;
          [self presentViewController:navigationController animated:YES completion:nil];
          if([[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPhone){
                navigationController.view.superview.frame = CGRectMake(0, 0, 320, 544);
                navigationController.view.frame =CGRectMake(108, 0, 320, 544);
                navigationController.view.superview.backgroundColor=[UIColor clearColor];
          }
    
    0 讨论(0)
  • 2021-01-31 19:46

    It's the same for me... I don't know yet how to solve it. I'm currently working in that issue so anything I get I'll share it!

    This is my code.

    -(IBAction)showGeneralSettings:(id)sender{
    
    self.generalSettingsVC = [[GeneralSettingsViewController alloc] initWithNibName:@"GeneralSettingsView" bundle:nil];
    
    //Present the view controller as a modal with a custom size (important to do after presenting it)
    self.generalSettingsVC.modalPresentationStyle = UIModalPresentationFormSheet;
    
    [self presentViewController:self.generalSettingsVC animated:YES completion:nil];
    
    self.generalSettingsVC.view.superview.frame = CGRectMake(0, 0, 497, 375);
    self.generalSettingsVC.view.superview.center = self.view.center;
    

    }

    0 讨论(0)
提交回复
热议问题