Mam UIPopoverController hostujący UINavigationController, który zawiera małą hierarchię kontrolerów widoku.
Postępowałem zgodnie z dokumentami i dla każdego kontrolera widoku ustawiam rozmiar kontekstu popover w następujący sposób:
[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
(rozmiar inny dla każdego kontrolera)
Działa to zgodnie z oczekiwaniami, gdy przechodzę do przodu w hierarchii - popover automatycznie animuje zmiany rozmiaru, aby odpowiadały wypchniętemu kontrolerowi.
Jednak gdy przechodzę „Wstecz” przez stos widoków za pomocą przycisku Wstecz na pasku nawigacji, okienko podręczne nie zmienia rozmiaru - pozostaje tak duże, jak osiągnięty najgłębszy widok. Wydaje mi się, że to zepsute; Spodziewałbym się, że popover będzie uwzględniał rozmiary, które są ustawione, gdy wyskakuje przez stos widoku.
Czy coś mi brakuje?
Dzięki.
viewWillAppear:
)?Odpowiedzi:
Ok, zmagałem się z tym samym problemem. Żadne z powyższych rozwiązań nie sprawdziło się dla mnie całkiem przyjemnie, dlatego zdecydowałem się trochę zbadać i dowiedzieć się, jak to działa. Oto, co odkryłem: - Kiedy ustawisz
contentSizeForViewInPopover
w kontrolerze widoku nie zostanie zmieniony przez samo okienko popover - nawet jeśli rozmiar okna popover może się zmienić podczas przechodzenia do innego kontrolera. - Kiedy rozmiar popover zmieni się podczas nawigacji do innego kontrolera, podczas cofania rozmiar popover nie przywróci - Zmiana rozmiaru popover w widoku WillAppear daje bardzo dziwną animację (kiedy powiedzmy, że popController wewnątrz popover) - Nie polecałbym tego - dla mnie ustawienie zakodowanego rozmiaru wewnątrz kontrolera w ogóle by nie działało - moje kontrolery muszą być czasami duże, a czasem małe - kontroler, który je przedstawi, ma jednak pojęcie o rozmiarzeRozwiązanie całego tego bólu jest następujące: Musisz zresetować rozmiar
currentSetSizeForPopover
in viewDidAppear. Ale musisz uważać, gdy ustawisz taki sam rozmiar, jaki był już ustawiony w polu,currentSetSizeForPopover
popover nie zmieni rozmiaru. Aby tak się stało, możesz najpierw ustawić fałszywy rozmiar (który będzie inny niż ustawiony wcześniej), a następnie ustawić odpowiedni rozmiar. To rozwiązanie będzie działać, nawet jeśli kontroler jest zagnieżdżony w kontrolerze nawigacji, a okno podręczne odpowiednio zmieni swój rozmiar, gdy będziesz nawigować z powrotem między kontrolerami.Możesz łatwo utworzyć kategorię na UIViewController za pomocą następującej metody pomocniczej, która załatwiłaby sprawę 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
wybranym kontrolerze.źródło
Oto jak rozwiązałem to na iOS 7 i 8:
W systemie iOS 8 system iOS dyskretnie zawija żądany widok w wyskakującym okienku do presentViewController kontrolera widoku PresentViewController. Jest wideo WWDC z 2014 roku wyjaśniające, co nowego w kontrolerze popover, w którym dotykają tego.
W każdym razie w przypadku kontrolerów widoku prezentowanych na stosie kontrolerów nawigacji, które wszystkie chcą mieć własny rozmiar, te kontrolery widoku muszą (w systemie iOS 8) wywołać ten kod w celu dynamicznego ustawienia preferowanego rozmiaru:
self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320, heightOfTable);
Zastąp heightOfTable obliczoną tabelą lub wysokością widoku.
Aby uniknąć dużej ilości duplikatów kodu i stworzyć wspólne rozwiązanie dla iOS 7 i iOS 8, utworzyłem kategorię na UITableViewController, aby wykonać tę pracę, gdy viewDidAppear jest wywoływany w moich tableviews:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self setPopOverViewContentSize]; }
Category.h:
#import <UIKit/UIKit.h> @interface UITableViewController (PreferredContentSize) - (void) setPopOverViewContentSize; @end
Category.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
źródło
presentingViewController
pracami. Jeśli ustawiępreferredContentSize
w,viewDidLoad
następuje dziwne zachowanie: powrót z innego kontrolera widoku w wyskakującym okienku prowadzi do nieprawidłowej zmiany rozmiaru okna podręcznego. Wygląda na to, że ustawiono zerowy rozmiar popover, ale rozmiar jest prawidłowy. W takim przypadku popover zajmuje całą wysokość ekranu. Czy wiesz, być może, dlaczego tak się dzieje? Nie mam ograniczenia przy zaimplementowanych 600 punktach, ponieważ z mojego doświadczenia wynika, że system operacyjny nie pozwala na określenie rozmiaru większego niż rozmiar ekranu.viewDidLoad
...To ulepszenie odpowiedzi Krasnyka .
Twoje rozwiązanie jest świetne, ale nie jest płynnie animowane.
Mała poprawa daje ładną animację:
Usuń ostatnią linię w
- (void) forcePopoverSize
metodzie:- (void) forcePopoverSize { CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f); self.contentSizeForViewInPopover = fakeMomentarySize; }
Umieść [self forcePopoverSize] w
- (void)viewWillAppear:(BOOL)animated
metodzie:- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self forcePopoverSize]; }
I na koniec - ustaw żądany rozmiar w
- (void)viewDidAppear:(BOOL)animated
metodzie:- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover; self.contentSizeForViewInPopover = currentSetSizeForPopover; }
źródło
Musisz ponownie ustawić rozmiar zawartości w
viewWillAppear
. Wywołując metodę delagate, w której ustawiasz rozmiar kontrolera popover. Miałem też ten sam problem. Ale kiedy to dodałem, problem został rozwiązany.Jeszcze jedno: jeśli używasz wersji beta mniejszych niż 5. Wtedy popover jest trudniejszy do zarządzania. Wydają się być bardziej przyjazne od wersji beta 5. Dobrze, że ostateczna wersja została wydana. ;)Mam nadzieję że to pomoże.
źródło
viewWillAppear
nie działa dla mnie. Ustawienie rozmiaru popovera wyraźnie zadziałało, ale to getto.We
-(void)viewDidLoad
wszystkich kontrolerach widoku, których używasz w kontrolerze nawigacji, dodaj:[self setContentSizeForViewInPopover:CGSizeMake(320, 500)];
źródło
Zresetowałem rozmiar w viewWillDisappear: (BOOL) animowana metoda kontrolera widoku, do którego wracam z:
-(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; CGSize contentSize = [self contentSizeForViewInPopover]; contentSize.height = 0.0; self.contentSizeForViewInPopover = contentSize; }
Następnie, gdy pojawia się widok, do którego wracamy, odpowiednio resetuję 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; }
źródło
W przypadku 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; }
Swoją drogą myślę, że to powinno być kompatybilne z poprzednimi wersjami iOS ...
źródło
willTransitionToTraitCollection
, wanimateAlongsideTransition
bloku zakończenia.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 !
źródło
U mnie to rozwiązanie działa. Jest to metoda z mojego kontrolera widoku, który rozszerza UITableViewController i jest kontrolerem głównym dla UINavigationController.
-(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.contentSizeForViewInPopover = self.tableView.bounds.size; }
I nie zapomnij ustawić rozmiaru zawartości dla kontrolera widoku, który zamierzasz umieścić w stosie nawigacyjnym
- (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]; }
źródło
jeśli możesz sobie wyobrazić asamblera, myślę, że jest trochę lepiej:
źródło
CGSizeZero
zamiast robić to samemu wCGSizeMake(0,0)
Odpowiedź Zaakceptowany nie działa dobrze z iOS 8. Co zrobiłem było stworzenie własną podklasę
UINavigationController
do użytku w tym popover i zastąpić metodępreferredContentSize
w ten sposób:- (CGSize)preferredContentSize { return [[self.viewControllers lastObject] preferredContentSize]; }
Co więcej, zamiast wywoływać
forcePopoverSize
(metoda implementowana przez @krasnyk) wviewDidAppear
, zdecydowałem się ustawić viewController (który pokazuje popover) jako delegata dla wcześniej wspomnianej nawigacji (w popover) i zrobić (co robi metoda force) w:-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
metoda delegata dla przekazanej metody
viewController
. Jedna ważna rzecz, robienieforcePopoverSize
wUINavigationControllerDelegate
metodzie jest w porządku, jeśli nie chcesz, aby animacja była płynna, jeśli tak, zostaw jąviewDidAppear
.źródło
Miałem ten sam problem, ale nie chcesz ustawiać contentize 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 wypchnięciem tego kontrolera do navigationController
źródło
Miałem szczęście, umieszczając następujące elementy w widoku:
[self.popoverController setPopoverContentSize:self.contentSizeForViewInPopover animated:NO];
Chociaż może to nie być ładnie animowane w przypadku, gdy popychasz / wyskakujesz popover o różnych rozmiarach. Ale w moim przypadku działa idealnie!
źródło
Wszystko, co musisz zrobić, to:
-W metodzie viewWillAppear elementu popOvers contentView, dodaj fragment podany poniżej. Będziesz musiał określić rozmiar popOver po raz pierwszy, gdy jest ładowany.
CGSize size = CGSizeMake(width,height); self.contentSizeForViewInPopover = size;
źródło
Miałem ten problem z kontrolerem popover, którego popoverContentSize = CGSizeMake (320, 600) na początku, ale stawał się większy podczas nawigacji po jego ContentViewController (a UINavigationController).
Kontroler nawigacyjny tylko wypychał i wyświetlał niestandardowe UITableViewControllers, więc w klasie viewDidLoad mojej niestandardowej tabeli kontrolera tabeli ustawiłem self.contentSizeForViewInPopover = CGSizeMake (320, 556)
44 mniej pikseli ma uwzględniać pasek nawigacyjny kontrolera Nav, a teraz nie mam już żadnych problemów.
źródło
Umieść to we wszystkich kontrolerach widoku, które pchasz w popover
CGSize currentSetSizeForPopover = CGSizeMake(260, 390); CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, currentSetSizeForPopover.height - 1.0f); self.contentSizeForViewInPopover = fakeMomentarySize; self.contentSizeForViewInPopover = currentSetSizeForPopover;
źródło
Rozwiązano ten sam problem i naprawiono go, ustawiając rozmiar widoku zawartości na kontroler nawigacji 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];
źródło
Chciałbym tylko zaproponować inne rozwiązanie, ponieważ żadne z nich nie zadziałało ...
Właściwie używam go z tym https://github.com/nicolaschengdev/WYPopoverController
Kiedy po raz pierwszy dzwonisz do wyskakującego okienka, 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 podrzędnych ...
źródło
Jest to poprawny sposób w iOS7, aby to zrobić, ustaw preferowany rozmiar zawartości w viewDidLoad w każdym kontrolerze widoku w stosie nawigacji (tylko raz). Następnie w viewWillAppear pobierz odniesienie do kontrolera popover i zaktualizuj tam contentSize.
-(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]; }
źródło
Rozwiązanie @krasnyk działało dobrze w poprzednich wersjach iOS, ale nie działało 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 również ma problem ze zmianą rozmiaru :(.
źródło
Musisz ustawić
preferredContentSize
właściwość NavigationController wviewWillAppear
:-(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.preferredContentSize = CGSizeMake(320, 500);}
źródło