J'ai quelques contrôleurs de vue modale d'une certaine taille. J'essaie d'éviter l'utilisation de vues personnalisées (création d'une superposition translucide noire en plein écran sur la vue actuelle, ajoutez la vue modale sur cette vue, faites les animations, etc.) pour la présenter car il n'y a pas de modalPresentationStyle qui correspond à la taille de mon contrôleurs.
Maintenant j'utilise UIModalPresentationPageSheet mais ma vue est plus petite en hauteur et j'ai un espace vide moche
Présentation souhaitée
_______________
| _______ |
| | | |
| | MyVC | |
| | | |
| ------- |
---------------
Présentation réelle
_______________
| | | |
| | MyVC | |
| | | |
| |-------| |
| | blank | |
---------------
Si j'utilise le UIModalPresentationFormSheet le conteneur est plus petit en largeur.
J'essaie de comprendre comment le faire, mais je ne sais pas si c'est possible. Quelle est la solution au problème de présentation d'un modal VC plus petit que n'importe lequel des PresentationStyles? La seule solution est d'organiser un "moteur de contrôleur de vue modal personnalisé"? Popovers ne correspond pas à ma conception exigences :(
Comme certains autres utilisateurs ici, j'ai également eu le problème que l'origine du contrôleur de vue modale n'était pas correcte. Après quelques expériences, j'ai trouvé une solution qui a fonctionné pour moi:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, <width>, <height>);
}
J'ai obtenu le résultat suivant ( texte du lien ) en utilisant:
self.modalPresentationStyle = UIModalPresentationFormSheet;
et en le présentant comme un contrôleur de vue modale. Faites-moi savoir si vous avez besoin d'aide.
Toutes ces réponses ne fonctionneront pas sur le SDK ios8.
Cela fonctionnera:
AboutViewController * _aboutViewController = [[AboutViewController alloc] init];
_aboutViewController.modalPresentationStyle = UIModalPresentationFormSheet;
if(IS_IOS8)
{
_aboutViewController.preferredContentSize = CGSizeMake(300, 300);
}
[self presentViewController:_aboutViewController animated:YES completion:nil];
Dans AboutViewController.m
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
if(!IS_IOS8)
{
self.view.superview.bounds = CGRectMake(0, 0, 300, 300);
}
}
IS_IOS8
#define IS_IOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
Dans iOS 8, vous pouvez également utiliser UIPresentationController qui vous offre plus d'options de personnalisation.
J'ai rencontré un problème pour que le modal de taille personnalisée soit centré jusqu'à ce que je comprenne ce que ViewController.view.superview.frame
a été défini initialement. Il est déterminé en fonction du type UIModalPresentation. superview.center
n'est même pas nécessaire (pour autant que mes tests le montrent).
De plus, j'ai défini les coordonnées dynamiquement en utilisant [UIScreen mainScreen].applicationFrame
, ne prenant en charge que l'orientation paysage pour l'instant. Vous devez effectuer une vérification conditionnelle pour prendre en charge le portrait et le paysage en inversant les valeurs X/Y et Hauteur/Largeur.
Voici ma première solution de travail pour iOS 6.0:
ViewController.modalPresentationStyle = UIModalPresentationFormSheet;
ViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:ViewController animated:YES completion:nil];
ViewController.view.superview.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
ViewController.view.superview.frame = CGRectMake(
// Calcuation based on landscape orientation (width=height)
([UIScreen mainScreen].applicationFrame.size.height/2)-(320/2),// X
([UIScreen mainScreen].applicationFrame.size.width/2)-(320/2),// Y
320,// Width
320// Height
);
Et puis j'ai regardé la réponse précédente et le visage a palmé. Raccourcit un peu ma solution en remplaçant la dernière ligne par:
ViewController.view.superview.bounds = CGRectMake(0, 0, 320, 320);
[~ # ~] éditez [~ # ~] pour la solution finale et les remarques.
La meilleure façon de procéder consiste à modifier la propriété des limites dans la vue d'ensemble de la vue présentée dans la feuille de formulaire. Lorsque vous présentez une vue de manière modale, la vue présentée est incorporée dans une autre vue.
Vous devez définir la propriété bounds de la superview sur le même rect que les limites de la vue. Ajoutez d'abord un ivar privé dans votre classe:
@implementation MySpecialFormsheet {
CGRect _realBounds;
}
Il vaut mieux le faire dans viewWillAppear:
. Ajoutez le code suivant au contrôleur de vue présenté de façon modale:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.view.superview.bounds = _realBounds;
}
Vous devez mettre en cache _realBounds
dans votre méthode viewDidLoad
:
- (void)viewDidLoad {
_realBounds = self.view.bounds;
[super viewDidLoad];
}
Ceci est ma solution pour une vue PAS de mise en page automatique (jamais essayée avec la mise en page automatique) et compatible avec iOS 7 et iOS 8.
Assurez-vous d'abord d'appeler la vue modale de cette façon:
CloudSettingsViewController *cloudController = [[CloudSettingsViewController alloc] initWithNibName:@"CloudSettingsView" bundle:nil];
CGRect originalBounds = cloudController.view.bounds;
cloudController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
cloudController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:cloudController animated:YES completion:nil];
Avec iOS 8, définissez PreferredContentSize dans la méthode viewDidLoad de la vue modale.
- (void)viewDidLoad {
[super viewDidLoad];
// backup of the original size (selected in interface builder)
height = self.view.frame.size.height;
width = self.view.frame.size.width;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) // versioni successive ios 8
self.preferredContentSize = CGSizeMake(width, height); // this is necessary to get the correct size of the modal view
}
Cela fonctionne AUSSI lorsque la vue modale doit afficher le clavier sur l'iPad.
Avec les versions précédentes d'iOS 8, vous devez définir les limites après l'appel de presentViewController:
[currentController presentViewController:controlPanelController animated:YES completion:nil];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8)
cloudController.view.superview.bounds = originalBounds;//it's important to do this after
même pour réduire la hauteur et la largeur de la feuille forma que vous pouvez utiliser
[self.view.superview setBounds:CGRectMake(0, 0, 450, 480)];
Les approches décrites ci-dessus doivent être modifiées pour iOS7:
// set desired bounds, then call -presentFromViewController:
@implementation PresentedViewController
{
CGRect _presentationBounds;
}
- (void)presentFromViewController:(UIViewController *)viewController
{
self.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
self.modalPresentationStyle = UIModalPresentationFormSheet;
_presentationBounds = self.view.bounds;
[viewController presentViewController:self animated:YES completion:nil];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (!CGRectIsEmpty(_presentationBounds))
{
self.view.superview.bounds = _presentationBounds;
_presentationBounds = CGRectZero;
}
}
(Ce code fonctionne également sur iOS6.)
Même moi, je me débattais avec le même problème pendant un bon moment. Après avoir donné quelques essais à partir de nombreuses réponses données ici, j'ai trouvé une solution qui a plutôt bien fonctionné pour moi.
Voici le code lors de la présentation du contrôleur de vue.
SomeViewController *sovcObj = [[SomeViewController alloc] initWithNibName:@"SyncOptionsViewController" bundle:nil];
someObj.modalPresentationStyle = UIModalPresentationFormSheet;
someObj.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:someObj animated:YES completion:nil];
someObj.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want
Dans le xib (si vous en utilisez un) dans la section 'Mesures simulées', sélectionnez la taille 'Forme libre'.
En dehors de cela, vous devez écrire le code ci-dessous dans votre contrôleur de vue présenté (c'est-à-dire, SomeViewController dans cet exemple)
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want
}
Ce code fonctionne également pour iOS 7
Une solution consiste à utiliser UIModalPresentationPageSheet pour présenter une feuille de page, puis redimensionner immédiatement la vue modale. Ceci est expliqué en détail dans cette réponse à une autre question .
Vous pouvez utiliser MZFormSheetController comme ceci:
MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithSize:customSize viewController:presentedViewController];
[presentingViewController mz_presentFormSheetController:formSheet animated:YES completionHandler:nil];
Redimensionnez la vue modale "après" qu'elle est présentée à l'aide de la méthode presentModalViewController. Consultez ce lien pour redimensionner la vue modale https://coderwall.com/p/vebqaq
Cette solution a fonctionné pour moi car j'avais le même problème.
Ma structure de vue modale est la suivante (j'utilise UIModalPresentationCurrentContext à la fois aux contrôleurs de présentation et aux contrôleurs présentés pour atteindre la transparence dans le VC présenté)
ModalViewController
> UIView (view) - resized to the same size as the presenting controller but has semi-translucent background - done automatically
>> UIView (contentView) - the true view with the content of the popup - this is the one that got consistently placed at the top of the screen all the time
Dans ModalViewController, j'ai remplacé la méthode suivante pour résoudre le problème de positionnement:
- (void) viewWillLayoutSubviews(){
[super viewWillLayoutSubviews];
CGRect r = self.view.bounds();
self.contentView.center = CGPointMake(r.size.width/2,r.size.height/2);
}
En fait, je crée et dimensionne d'abord la vue du contenu, mais selon une méthode différente.
J'espère que cela aide quelqu'un.