objective c - Popover con ModalPresentationStyle no está centrado en iOS 7 iPad
objective-c ios7 (6)
Tengo un problema con iOS 7 que parece ser un error o simplemente no hago algo bien. Tengo modalViewController que aparece como una ventana emergente en iPad con ModalPresentationStyle. Y no es de tamaño estándar, tamaño personalizado. Aquí está el código:
myViewController *myVC = [[myViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:myVC];
[nav setModalPresentationStyle:UIModalPresentationFormSheet];
[nav setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
[self presentViewController:nav animated:YES completion:nil];
nav.view.superview.bounds = CGRectMake(0, 0, 320, 465);
Todo funciona bien en iOS 6, pero en iOS 7 no está centrado. Pero si configuro ModalTransitionStyle en UIModalTransitionStyleCrossDissolve, funciona bien. Pero solo en este modo. Tal vez alguien se tropezó con este también y sabe cómo solucionarlo? No soy un gran fanático del efecto de disolución. Gracias.
Es lo mismo para mí ... Todavía no sé cómo resolverlo. Actualmente estoy trabajando en ese tema, ¡así que cualquier cosa que obtenga lo compartiré!
Este es mi código.
-(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;
}
Hice esto de forma ligeramente diferente utilizando un controlador de navegación subclasificado y AutoLayout en Swift, para centrar la vista en la vista de supervisión en una anchura y altura determinadas. Mi caso particular necesitaba soporte para iPad y iOS7-8 (hay algunas constantes específicas de mi proyecto en este código, pero entiendes la 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)
}
}
La solución anterior no funcionó para mí. Utilicé lo siguiente:
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];
}
Para mí, el problema era llamar a becomeFirstResponder
en un campo de texto en viewDidAppear
del controlador de vista presentado. Parece ser un error con eso ahora. La solución lo envolvió en un simple dispatch_async
:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
dispatch_async(dispatch_get_main_queue(), ^{
[self.userNameTextField becomeFirstResponder];
});
}
Tengo un método en el que el antiguo estilo de presentación modal personalizada de la fromsheet
funciona con iOS <=7
aunque puede configurar custom height and width
.
Tenga en cuenta que es posible que este método no funcione en una versión más nueva en el futuro.
- (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();
});
}
Yo tuve el mismo problema. He resuelto esto utilizando otro enfoque, que se encuentra here .
Lo que propone esta solución es utilizar el método (void)viewWillLayoutSubviews
Entonces, en el caso de @Manuel M. dentro de GeneralSettingsViewController
agregue el siguiente código:
// GeneralSettingsViewController
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 497, 375);
}
Y ya no necesitarás este código:
self.generalSettingsVC.view.superview.frame = CGRectMake(0, 0, 497, 375);
self.generalSettingsVC.view.superview.center = self.view.center;
Para @titicaca, está utilizando un UINavigationController
No lo he probado con este controlador, pero podría probar la misma solución que mencioné, extendiendo el UINavigationController
y sobrescribiendo el método viewWillLayoutSubviews
.
[EDITAR]
Para @titicaca lo probé en un nuevo proyecto y para mí funcionó. Lo que hice fue tener un controlador de vista de navegación personalizado, CustomNavigationController
anulando el viewWillLayoutSubviews
como esto:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 330, 284);
}
Luego, el controlador de vista que presenta el CustomNavigationController
debe ejecutar un código similar a este:
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];
Sin embargo, debe asegurarse de que las dimensiones de self.view.superview.bounds = CGRectMake(0, 0, 330, 284);
son números pares, de lo contrario el texto en el interior se vuelve borroso, si hay alguno