UIPopoverController ändert die Größe automatisch auf die maximale Höhe von pushViewController

69

Ich habe ein Popover mit einem UINavigationController. Ich kann das Popover gut anzeigen, und es enthält den navController ganz gut. Der navController enthält eine Tabellenansicht. Wenn ich ein Element auswähle, wird eine neue Detailansicht erstellt:

     DeviceDetailViewController *detailViewController = 
[[[DeviceDetailViewController alloc] initWithNibName:@"DeviceDetailViewController" bundle:nil] autorelease];

Ich schiebe es dann auf den neuen View Controller:

    [self.navigationController pushViewController:detailViewController animated:YES];

In diesem Fall tritt das Problem auf: Nach dem Drücken der neuen Ansicht wird die Größe des Popovers auf die auf dem iPad verfügbare maximale Höhe geändert.

Ich habe versucht, die Höhe aller Ansichten in der xib auf eine feste Höhe anstatt auf eine flexible einzustellen. Ich habe versucht, die Höhe des Popovers explizit einzustellen. Ich habe auch versucht, verschiedene Ansichts-Controller als untergeordnete Ansicht zu verwenden. Das Problem bleibt bestehen: Das Popover möchte die Größe automatisch auf die maximale Höhe ändern, wenn eine neue Ansicht auf den Navigationscontroller verschoben wird.

In dieser Frage wird der Versuch erörtert, die Größe des Popovers beim Verschieben neuer Ansichten gezielt zu steuern:

Ich dachte, dies könnte eine Brute-Force-Methode sein, um die Größe zu kontrollieren. Seltsamerweise führt dies jedoch zu einigen schnellen Grafikproblemen (als würde die Ansicht frisch animiert), gefolgt von einer weiteren Größenänderung wie oben beschrieben.

Mit anderen Worten, zwingt etwas buchstäblich die popover auf seine maximale Höhe, und es scheint , aufzutreten , nachdem alle aufgerufen wurden.

Ist es der Navigationscontroller? Hat jemand so etwas gesehen?

SG1
quelle

Antworten:

123

Dies hat es für mich behoben, nachdem ich das gleiche Problem hatte (zufällig auch heute):

BEARBEITEN : Wie contentSizeForViewInPopoverin iOS7.0so Verwendung veraltet preferredContentSize.

Ursprüngliche Antwort unten :

Fügen Sie detailViewControllerFolgendes hinzu:

- (void)viewWillAppear:(BOOL)animated {

    CGSize size = CGSizeMake(320, 480); // size of view in popover
    self.contentSizeForViewInPopover = size;

    [super viewWillAppear:animated];

}

Sie möchten auch etwas Ähnliches zu Ihrem ursprünglichen DeviceDetailViewController hinzufügen, um eine Größenänderung beim Tippen auf das hintere NavbarItem zu vermeiden.

gegabelt
quelle
4
Vielen Dank! Ich hatte das gleiche Problem und das contentSizeForViewInPopover-Attribut von UIViewController hat es behoben.
titaniumdecoy
Danke, du hast meinen Tag gerettet: D
Yildiray Meric
2
In mindestens einem Fall musste ich die Popup-Höhe noch explizit selbst festlegen (wenn der Popover-Controller bereits mit einer definierten Höhe sichtbar war). Andernfalls funktionierte dies für die Rückkehr zu einer vorherigen Seite in einem Navigationscontroller.
Kendall Helmstetter Gelner
BEEINDRUCKEND! Das war schwer zu finden. Vielen Dank. Das hilft wirklich. Wenn der Ansichts-Controller in einem Popup manuell gedreht wurde, ändern alle Push-Ansichts-Controller ihre Größe. Mit dieser Problemumgehung wird alles reibungslos. Ich suchte nach Tagen für eine Lösung wie diese.
JackPearse
1
Dies funktioniert nicht für mich, muss es in viewDidLoad, nicht viewWillAppear
daidai
30

Ähnlich wie beim Umgang damit viewWillAppearbesteht eine andere Möglichkeit, damit umzugehen, darin, sie zu überschreiben contentSizeForViewInPopover. Sehr knapp:

-(CGSize)contentSizeForViewInPopover
{
    return self.view.bounds.size;
}
Peter DeWeese
quelle
Funktioniert mit iOS5.borked Lösung schien nicht mit ios5 zu funktionieren.
Palaniraja
1
In meinem Fall hat dies das Popover nur auf die Größe des gesamten Bildschirms gebracht.
Greg Maletic
@ Greg Maletic, welche Ansicht war self.viewin Ihrem Fall? Ich habe es gerade noch einmal getestet und es funktioniert immer noch.
Peter DeWeese
@PeterDeWeese sehen den Header für diese Eigenschaft: Mit dieser Option contentSizeForViewInPopoverkönnen Sie die Größe des Inhalts im Ansichts-Controller festlegen. Diese Eigenschaft ist Lese- / Schreibzugriff und sollte im Allgemeinen nicht überschrieben werden .
Bis zum
@ Bis zum Festlegen der Eigenschaft bei contentViewController viewWillAppearhat es bei mir nie funktioniert, während das Überschreiben des Getters immer funktioniert hat.
A-Live
30

Für IOS5

Ich empfehle Ihnen, dies zu tun in:

- (void)viewDidLoad {
    [super viewDidLoad];

    CGSize size = CGSizeMake(320, 480); // size of view in popover
    self.contentSizeForViewInPopover = size;

}
MUH Mobile Inc.
quelle
Dies funktioniert bei mir nicht. Wenn Sie einen Ansichts-Controller öffnen, wird die Höhe dieses Controllers nicht wiederhergestellt, obwohl die richtige Breite für diesen Controller wiederhergestellt wird. Bitte sehen Sie mein offenes Repo, bitbucket.org/danielphillips/uipopovercontroller-resize-bug
Daniel
11

Ich hatte ein ähnliches Problem.

Ich hatte ein Popover von einer Schaltfläche in einer Symbolleiste. Das Popover wurde auf eine bestimmte Größe eingestellt. Es war eine Tabellenansicht. Bei Auswahl der Tabellenzeile wurde ein neuer View Controller mit einem Navigationscontroller aufgerufen.

Wenn die Schaltfläche "Zurück" ausgewählt wurde, wurde das Popover anstelle der gewünschten Größe die Standardgröße (320 x 1100, glaube ich).

Der ursprüngliche Code war:

  MyTableViewController *myVC = [[MyTableViewController alloc] init];
  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC];

  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
  popover.delegate = self;

  popover.popoverContentSize = CGSizeMake(400.0, 500.0);

  [myVC release];
  [navController release];
  [popover release];

Ich habe eine Zeile hinzugefügt, um das Problem zu lösen. Zugegeben, es ist eine Art Umgehung, weil ich die Höhe des Headers subtrahieren musste. Vielleicht könnte einer von euch mich mit einer besseren Methode aufklären. Wie auch immer, es funktioniert.

  MyTableViewController *myVC = [[MyTableViewController alloc] init];

  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC];

  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
  popover.delegate = self;

  popover.popoverContentSize = CGSizeMake(400.0, 500.0);

  //Subtract the height of the header to match the total popover size (not just the view).
  myVC.contentSizeForViewInPopover = CGSizeMake(400.0, 500-44);

  [myVC release];
  [navController release];
  [popover release];

Ich glaube, wenn ein Navigationscontroller beteiligt ist und die Zurück-Taste gedrückt wird, wird das Popover auf die Standardgröße zurückgesetzt. Durch Hinzufügen der contentSizeForViewInPopover-Eigenschaft für den Ansichtscontroller myVC wird die spezifische Größe erzwungen.

Hoffe das ist hilfreich.

Kurt

Kurt
quelle
Andere Optionen funktionierten nicht, als ich einen vorhandenen Ansichts-Controller durch einen neuen in einem bereits veränderten Popover-Controller ersetzte. Diese Option funktionierte
Yogev Shelly
9

Verwenden Sie für iOS 7 Folgendes:

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGSize size = CGSizeMake(320, 768); // size of view in popover
    self.preferredContentSize = size;
}

UIViewController.contentSizeForViewInPopover wurde zuerst in iOS 7 veraltet.

Abdullah Umer
quelle
6

Als Reaktion auf grafische Störungen mit Animationen:

Die UIPopoverController-Animationen stehen in Konflikt mit den UINavigation Controller-Animationen, wenn Sie das Popover mit einem darin enthaltenen UINavigationController erstellen. Dies führt zu grafischen Störungen beim Animieren. Um das Problem zu beheben, setzen Sie den animierten Parameter beim Drücken anderer Controller oder beim Anzeigen der Symbolleiste auf false.

Pushing View Controller:

[self.navigationController pushViewController:detailViewController animated:NO];

Die Symbolleiste sichtbar machen:

[[self navigationController] setToolbarHidden:NO animated:NO]; 

Einstellen der Animation: NEIN lässt die Animationen in einem UIPopoverController korrekt aussehen.

Paul Solt
quelle
Die Animationskonflikte zwischen UIPopoverController und [UINavigationController setToolbarHidden: animiert:] waren ein Problem, mit dem ich konfrontiert war. Guter Tipp, da das Update nicht intuitiv ist. setToolbarHidden ohne Animation zeigt / versteckt die Symbolleiste mit der Animation, die vom UIPopoverController verarbeitet wird, wie Sie sagen. Sehr subtiles, aber nerviges Gotcha.
Chris Miles
5

Warum nicht einfach das einstellen, contentSizeForViewInPopoverbevor Sie den nächsten Controller auf den Navigationsstapel schieben? Keine Notwendigkeit, Größen viewWillAppearund dergleichen einzustellen .

[nextController setContentSizeForViewInPopover:[self contentSizeForViewInPopover]];
[[self navigationController] pushViewController:nextController animated:YES];

Funktioniert unter IOS 5.1

MrJre
quelle
1
contentSizeForViewInPopoverist in iOS7 veraltet, preferredContentSizefunktioniert aber auch.
Regan Sarwas
4

Nach dem Rat von borked (der mich in die richtige Richtung gelenkt hat, danke dafür!), Was ich mache, wenn ich einen neuen Controller drücke, um die Größe beizubehalten, bevor ich ihn drücke:

productViewController.contentSizeForViewInPopover = self.view.bounds.size;
self.contentSizeForViewInPopover = self.view.bounds.size;

[self.navigationController pushViewController:productViewController animated:YES];

Ich mag das, weil ich die Popover-Werte nicht in jedem View-Controller fest codieren muss (gut, da ich sie in verschiedenen Höhen verwende).

Die self.contentSizeForViewInPopoverLinie soll die Größe beibehalten, wenn der Benutzer zurückschlägt . Ich denke, Sie könnten diese Zeile woanders platzieren, wieviewWillAppear oder wo immer Sie möchten.

Scheint zu funktionieren ...

William Denniss
quelle
2

Schreiben Sie in die - (void) viewDidLoad aller View Controller, die Sie in der Navigation verwenden, den folgenden Code:

self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
MouzmiSadiq
quelle
2

Es gibt zwei Möglichkeiten, den contentSizeForViewInPopover im Storyboard festzulegen. Sie können Ihre Ansichts-Controller, die sich in Ihrem Navigations-Controller befinden, auf FreeForm einstellen und die Stammansichten auf die gewünschte Größe einstellen. Sie können die simulierte Metrik auch als abgeleitet beibehalten und "Explizite Größe verwenden" aktivieren und dort die gewünschte Größe festlegen.

Fügen Sie dann in jedem Ansichts-Controller, der sich in Ihrem Navigations-Controller befindet, Folgendes hinzu ...

- (void)viewDidAppear:(BOOL)animated {
     [super viewDidAppear:animated];

     ["yourpopoverController" setPopoverContentSize:CGSizeMake(self.
           contentSizeForViewInPopover.width, seld.contentSizeForViewInPopover.height + self.
           navigationController.navigationBar.frame.size.height) animated:YES];
}

In der Übergangsanimation wird die neue Ansicht an der Oberseite ausgerichtet und die Höhe entsprechend angepasst.

Auf diese Weise müssen Sie contentSizeForViewInPopover nicht überschreiben oder eine andere Größe speziell in Ihren Ansichtscontrollern angeben. Es ist alles im Storyboard.

Wenn einer Ihrer Ansichts-Controller eine variable Höhe hat, müssen Sie contentSizeForViewInPopover in dieser Ansicht wie folgt überschreiben ...

- (CGSize)contentSizeForViewInPopover {
    return CGSizeMake(450, "calculate your height here");
}
Matt Becker
quelle
1

Dieses Zeug hat vielleicht einmal funktioniert, aber nicht mit xCode 6, bei dem contentSizeForViewInPopover veraltet ist. Zum Glück wird es beim Laden des Storyboards respektiert. Ich habe einen XML-Editor (Xmplify) heruntergeladen und das Storyboard gehackt. Stellen Sie den Schlüssel contentSizeForViewInPopover auf die gewünschte Größe ein. Speichern und ersetzen Sie das Storyboard (erstellen Sie zuerst eine Kopie).

Genauer :

< viewController>

     <value key="contentSizeForViewInPopover" type="size" width="450" height="280" / >

</viewController>
Joe313
quelle
0

Arbeite nicht für mich, wenn ich das benutze:

[UIPopoverController 
    [UINavigationController] = root vc = [UIViewController vc1] => [UIViewController vc2] 
]

Wenn Popover angezeigt wird, drücken Sie die Taste auf VC1 und drücken Sie VC2 auf den Navigationscontroller

Als nächstes kehren Sie zu vc1 (root) zurück und drücken die Taste in vc2 (popToRootViewController-Methode).

Wir können sehen, dass Popover seine eigene Größe ändert, aber die Größe von VC1 ist alt ... WAS IST DAS ???

Ok, jetzt funktioniert ... Popover-Eigenschaft in meinem Controller hinzufügen

self.contentSizeForViewInPopover = (CGSize){400, 200};
self.navigationController.contentSizeForViewInPopover = self.contentSizeForViewInPopover;
self.popover.popoverContentSize = self.contentSizeForViewInPopover;
iTux
quelle
0

Unter Swift 4 und iOS 11 war für mich die einzig mögliche Lösung. Zur Nutzung showViewController:sender: and showDetailViewController:sender:statt presentViewController:animated:completion:.

Aus dem Apple Doc

Die Methoden showViewController: sender: und showDetailViewController: sender: bieten die anpassungsfähigste und flexibelste Möglichkeit, View Controller anzuzeigen. Mit diesen Methoden kann der Controller für die Präsentationsansicht entscheiden, wie mit der Präsentation am besten umgegangen werden soll. Beispielsweise kann ein Container-View-Controller den View-Controller als untergeordnetes Element einbinden, anstatt ihn modal darzustellen. Das Standardverhalten zeigt den View Controller modal an.

BilalReffas
quelle