Popover z wbudowanym kontrolerem nawigacyjnym nie uwzględnia rozmiaru NAV z tyłu
Mam UIPopoverController hostujący UINavigationController, który zawiera małą hierarchię kontrolerów widoku.
Podążałem za dokumentami i dla każdego kontrolera widoku ustawiałem rozmiar kontekstu widoku tak:
[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
(rozmiar inny dla każdego kontrolera)
Działa to zgodnie z oczekiwaniami, gdy poruszam się do przodu w hierarchii - wyskakujące okienko automatycznie animuje zmiany rozmiaru, aby odpowiadały pchniętemu kontrolerowi.
Jednakże, kiedy Przejdź "wstecz" przez stos widoku za pomocą przycisku Wstecz paska nawigacji, wyskakujące okienko nie zmienia rozmiaru-pozostaje tak duże, jak najgłębszy widok osiągnięty. Wydaje mi się to złamane; spodziewałbym się, że popover szanuje rozmiary, które są skonfigurowane, gdy przeskakuje przez stos widoku.
Czy coś przeoczyłem? Dzięki.21 answers
Ok, zmagałem się z tym samym problemem. Żadne z powyższych rozwiązań nie zadziałało dla mnie całkiem ładnie, dlatego postanowiłem przeprowadzić małe dochodzenie i dowiedzieć się, jak to działa.
Oto co odkryłem:
- Po ustawieniu contentSizeForViewInPopover
w kontrolerze widoku nie zostanie ona zmieniona przez samo wyskakujące okienko - nawet jeśli rozmiar wyskakującego okienka może się zmienić podczas przechodzenia do innego kontrolera.
- Gdy rozmiar wyskakującego zmieni się podczas przechodzenia do innego kontrolera, podczas powrotu, rozmiar popover nie przywraca
- Zmiana rozmiaru popover w viewWillAppear daje bardzo dziwną animację ( gdy powiedzmy popController wewnątrz popover) - nie polecam
- Dla mnie ustawienie twardego rozmiaru wewnątrz kontrolera w ogóle nie zadziała - moje Kontrolery muszą być czasami duże, czasami małe-kontroler, który je zaprezentuje, ma pomysł na rozmiar
Rozwiązanie tego bólu jest następujące:
Musisz zresetować Rozmiar currentSetSizeForPopover
w viewDidAppear. Ale musisz być ostrożny, gdy ustawisz ten sam rozmiar, jaki był już ustawiony w polu currentSetSizeForPopover
, wtedy popover nie zmieni rozmiaru. Aby tak się stało, możesz najpierw ustawić fałszywy rozmiar (który będzie inny niż ten, który został ustawiony wcześniej), a następnie ustawić odpowiedni rozmiar. To rozwiązanie będzie działać, nawet jeśli kontroler jest zagnieżdżony wewnątrz kontrolera Nawigacyjnego, a popover zmieni odpowiednio jego rozmiar, gdy będziesz poruszać się z powrotem między kontrolerem nawigacyjnym Kontrolery.
Możesz łatwo utworzyć kategorię w UIViewController za pomocą poniższej metody pomocniczej, która zrobiłaby sztuczkę z ustawieniem rozmiaru:
- (void) forcePopoverSize {
CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f);
self.contentSizeForViewInPopover = fakeMomentarySize;
self.contentSizeForViewInPopover = currentSetSizeForPopover;
}
Następnie po prostu wywołaj go w -viewDidAppear
pożądanego kontrolera.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-17 18:17:29
Oto jak rozwiązałem to dla iOS 7 i 8:
W systemie iOS 8 iOS po cichu zawija żądany widok w wyskakującym okienku do presentedViewController kontrolera widoku presentingViewController. Jest film WWDC z 2014 roku wyjaśniający, co nowego w popovercontrollerze, gdzie dotykają tego.
W każdym razie, dla kontrolerów widoków prezentowanych na stosie kontrolerów nawigacyjnych, które chcą mieć własne rozmiary, te kontrolery widoku muszą (w systemie iOS 8) wywołać ten kod dynamicznie ustawia preferredContentSize:
self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320, heightOfTable);
Zastąp wysokość z obliczoną tabelą lub wysokością widoku.
Aby uniknąć wielu duplikatów kodu i stworzyć wspólne rozwiązanie iOS 7 i iOS 8, utworzyłem kategorię na UITableViewController, aby wykonać tę pracę, gdy viewdidappear jest wywoływany w moich przeglądach tableviews:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self setPopOverViewContentSize];
}
Kategoria.h:
#import <UIKit/UIKit.h>
@interface UITableViewController (PreferredContentSize)
- (void) setPopOverViewContentSize;
@end
Kategoria.m:
#import "Category.h"
@implementation UITableViewController (PreferredContentSize)
- (void) setPopOverViewContentSize
{
[self.tableView layoutIfNeeded];
int heightOfTable = [self.tableView contentSize].height;
if (heightOfTable > 600)
heightOfTable = 600;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
self.preferredContentSize=CGSizeMake(320, heightOfTable);
else
self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320, heightOfTable);
}
}
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-17 02:59:45
Jest to poprawa w odpowiedzi krasnyka .
Twoje rozwiązanie jest świetne, ale nie jest płynnie animowane.
Mała poprawa daje miłą animację:
Usuń ostatni wiersz w metodzie - (void) forcePopoverSize
:
- (void) forcePopoverSize {
CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f);
self.contentSizeForViewInPopover = fakeMomentarySize;
}
Put [self forcePopoverSize] in - (void)viewWillAppear:(BOOL)animated
method:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self forcePopoverSize];
}
I na koniec-ustaw żądany rozmiar w metodzie - (void)viewDidAppear:(BOOL)animated
:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
self.contentSizeForViewInPopover = currentSetSizeForPopover;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 08:53:57
Musisz ponownie ustawić rozmiar zawartości w viewWillAppear
. Wywołując metodę delagate, w której ustawia się rozmiar popovercontrollera. Też miałem ten sam problem. Ale kiedy to dodałem, problem rozwiązany.
Jeszcze jedno: jeśli używasz wersji beta mniejszej niż 5. Wtedy popovery są trudniejsze do zarządzania. Wydają się być bardziej przyjazne od wersji beta 5. Dobrze, że wyszła finalna wersja. ;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-07 11:03:33
W -(void)viewDidLoad
wszystkich kontrolerów widoku używanych w kontrolerze nawigacyjnym dodaj:
[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-20 12:25:12
Zresetowałem rozmiar w viewWillDisappear: (BOOL)animowana metoda kontrolera widoku, który jest nawigowany z powrotem:
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
CGSize contentSize = [self contentSizeForViewInPopover];
contentSize.height = 0.0;
self.contentSizeForViewInPopover = contentSize;
}
Następnie, gdy pojawi się widok nawigowany z powrotem do, odpowiednio zresetuję Rozmiar:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
CGSize contentSize;
contentSize.width = self.contentSizeForViewInPopover.width;
contentSize.height = [[self.fetchedResultsController fetchedObjects] count] * self.tableView.rowHeight;
self.contentSizeForViewInPopover = contentSize;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-20 12:35:10
Dla iOS 8 działa:
- (void) forcePopoverSize {
CGSize currentSetSizeForPopover = self.preferredContentSize;
CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f);
self.preferredContentSize = fakeMomentarySize;
self.navigationController.preferredContentSize = fakeMomentarySize;
self.preferredContentSize = currentSetSizeForPopover;
self.navigationController.preferredContentSize = currentSetSizeForPopover;
}
BTW myślę, że to powinno być zgodne z poprzednimi wersjami iOS...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-29 08:50:52
Well i worked out. Have a look.
Made a ViewController in StoryBoard. Associated with PopOverViewController class.
import UIKit
class PopOverViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.preferredContentSize = CGSizeMake(200, 200)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss:")
}
func dismiss(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
See ViewController:
//
// ViewController.swift
// iOS8-PopOver
//
// Created by Alvin George on 13.08.15.
// Copyright (c) 2015 Fingent Technologies. All rights reserved.
//
import UIKit
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate
{
func showPopover(base: UIView)
{
if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("popover") as? PopOverViewController {
let navController = UINavigationController(rootViewController: viewController)
navController.modalPresentationStyle = .Popover
if let pctrl = navController.popoverPresentationController {
pctrl.delegate = self
pctrl.sourceView = base
pctrl.sourceRect = base.bounds
self.presentViewController(navController, animated: true, completion: nil)
}
}
}
override func viewDidLoad(){
super.viewDidLoad()
}
@IBAction func onShow(sender: UIButton)
{
self.showPopover(sender)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .None
}
}
Note: The func showPopover(base: UIView) method should be placed before ViewDidLoad. Hope it helps !
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-11 06:04:58
Dla mnie To rozwiązanie działa. Jest to metoda z mojego kontrolera widoku, która rozszerza UITableViewController i jest głównym kontrolerem dla UINavigationController.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.contentSizeForViewInPopover = self.tableView.bounds.size;
}
I nie zapomnij ustawić rozmiaru zawartości kontrolera widoku, który będzie wepchnięty do stosu nawigacji
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
dc = [[DetailsController alloc] initWithBookmark:[[bookmarksArray objectAtIndex:indexPath.row] retain] bookmarkIsNew:NO];
dc.detailsDelegate = self;
dc.contentSizeForViewInPopover = self.contentSizeForViewInPopover;
[self.navigationController pushViewController:dc animated:YES];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-05 06:22:28
Jeśli potrafisz sobie wyobrazić assamblera, to myślę, że to jest nieco lepsze:
- (void) forcePopoverSize { CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; self.contentSizeForViewInPopover = CGSizeMake(0, 0); self.contentSizeForViewInPopover = currentSetSizeForPopover; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-30 04:30:26
Zaakceptowana odpowiedź nie działa dobrze z iOS 8. To, co zrobiłem, to stworzenie własnej podklasy UINavigationController
do użycia w tym popover i nadpisanie metody preferredContentSize
w ten sposób:
- (CGSize)preferredContentSize {
return [[self.viewControllers lastObject] preferredContentSize];
}
Ponadto, zamiast wywoływać forcePopoverSize
(metodę zaimplementowaną przez @krasnyk) w viewDidAppear
postanowiłem ustawić viewController (który pokazuje popover) jako delegat dla wcześniej wspomnianej nawigacji (w popover) i do (co robi metoda force) w:
-(void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
Metoda delegowania dla zdanego viewController
. Jedna ważna rzecz, Robienie forcePopoverSize
w metodzie UINavigationControllerDelegate
jest w porządku, jeśli nie potrzebujesz, aby animacja była płynna, jeśli tak, to zostaw ją w viewDidAppear
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:06
Miałem ten sam problem, ale nie chcesz ustawiać contentsize w metodzie viewWillAppear lub viewwilldisappear.
AirPrintController *airPrintController = [[AirPrintController alloc] initWithNibName:@"AirPrintController" bundle:nil];
airPrintController.view.frame = [self.view frame];
airPrintController.contentSizeForViewInPopover = self.contentSizeForViewInPopover;
[self.navigationController pushViewController:airPrintController animated:YES];
[airPrintController release];
Ustaw właściwość contentSizeForViewInPopover dla tego kontrolera przed naciśnięciem kontrolera do navigationController
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-03 06:38:27
Poszczęściło mi się umieszczając w widoku:
[self.popoverController setPopoverContentSize:self.contentSizeForViewInPopover animated:NO];
Chociaż może to nie animować ładnie w przypadku, gdy pchasz / popping popovers różnej wielkości. Ale w moim przypadku działa idealnie!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-21 00:43:05
Wszystko co musisz zrobić to:
-w metodzie viewwillappear w popOvers contentView dodaj poniższy fragment. Musisz podać rozmiar popOver po raz pierwszy, gdy jest ładowany.
CGSize size = CGSizeMake(width,height);
self.contentSizeForViewInPopover = size;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-06 18:48:12
Miałem ten problem z kontrolerem popover, którego popoverContentSize = CGSizeMake (320, 600) na początku, ale byłby większy podczas poruszania się po ContentViewController (UINavigationController).
Kontroler nav tylko pchał i popping custom uitableviewcontrollers, więc w moim custom table view controller class ' S viewDidLoad ustawiłem self.contentSizeForViewInPopover = CGSizeMake (320, 556)
44 mniej pikseli ma odpowiadać nav kontrolera Nav bar, a teraz nie mam już żadnych problemów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-04 21:52:32
Umieść to we wszystkich kontrolerach widoku, które wciskasz w popover
CGSize currentSetSizeForPopover = CGSizeMake(260, 390);
CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f,
currentSetSizeForPopover.height - 1.0f);
self.contentSizeForViewInPopover = fakeMomentarySize;
self.contentSizeForViewInPopover = currentSetSizeForPopover;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 06:35:54
Napotkał ten sam problem i naprawił go, ustawiając rozmiar widoku zawartości na Kontroler nawigacyjny i kontroler widoku przed umieszczeniem init UIPopoverController.
CGSize size = CGSizeMake(320.0, _options.count * 44.0);
[self setContentSizeForViewInPopover:size];
[self.view setFrame:CGRectMake(0.0, 0.0, size.width, size.height)];
[navi setContentSizeForViewInPopover:size];
_popoverController = [[UIPopoverController alloc] initWithContentViewController:navi];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-26 14:46:06
Chciałbym zaproponować inne rozwiązanie, ponieważ żadne z nich nie działało na mnie...
Używam go z tym https://github.com/nicolaschengdev/WYPopoverController
Po pierwszym wywołaniu popup użyj tego.
if ([sortTVC respondsToSelector:@selector(setPreferredContentSize:)]) {
sortTVC.preferredContentSize = CGSizeMake(popoverContentSortWidth,
popoverContentSortHeight);
}
else
{
sortTVC.contentSizeForViewInPopover = CGSizeMake(popoverContentSortWidth,
popoverContentSortHeight);
}
Następnie w tym wyskakującym okienku użyj tego.
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
if ([self respondsToSelector:@selector(setPreferredContentSize:)]) {
self.preferredContentSize = CGSizeMake(popoverContentMainWidth,
popoverContentMainheight);
}
else
{
self.contentSizeForViewInPopover = CGSizeMake(popoverContentMainWidth,
popoverContentMainheight);
}
}
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:YES];
self.contentSizeForViewInPopover = CGSizeZero;
}
Następnie powtórz dla widoków potomnych...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-30 12:41:37
Jest to prawidłowy sposób w iOS7, aby to zrobić, Ustaw preferowany rozmiar zawartości w viewDidLoad dla każdego kontrolera widoku w stosie nawigacji(tylko raz). Następnie w viewWillAppear uzyskaj odniesienie do kontrolera popover i zaktualizuj tam rozmiar zawartości.
-(void)viewDidLoad:(BOOL)animated
{
...
self.popoverSize = CGSizeMake(420, height);
[self setPreferredContentSize:self.popoverSize];
}
-(void)viewWillAppear:(BOOL)animated
{
...
UIPopoverController *popoverControllerReference = ***GET REFERENCE TO IT FROM SOMEWHERE***;
[popoverControllerReference setPopoverContentSize:self.popoverSize];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-25 18:19:22
@krasnyk rozwiązanie działało dobrze w poprzednich wersjach iOS, ale nie działa w iOS8. Poniższe rozwiązanie zadziałało dla mnie.
- (void) forcePopoverSize {
CGSize currentSetSizeForPopover = self.preferredContentSize;
//Yes, there are coupling. We need to access the popovercontroller. In my case, the popover controller is a weak property in the app's rootVC.
id mainVC = [MyAppDelegate appDelegate].myRootVC;
if ([mainVC valueForKey:@"_myPopoverController"]) {
UIPopoverController *popover = [mainVC valueForKey:@"_myPopoverController"];
[popover setPopoverContentSize:currentSetSizeForPopover animated:YES];
}
}
Nie jest to najlepsze rozwiązanie, ale działa.
Nowy UIPopoverPresentationController ma również problem ze zmianą rozmiaru: (.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-01 07:49:43
Musisz ustawić preferredContentSize
właściwość NavigationController w viewWillAppear
:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.preferredContentSize = CGSizeMake(320, 500);}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-21 08:28:29