Как правильно разместить popover в iOS 8
Я пытаюсь добавить UIPopoverView в свое приложение Swift для iOS 8, но не могу получить доступ к свойству PopoverContentSize, поскольку всплывающее окно не отображается в правильной форме. мой код:
var popover: UIPopoverController? = nil
func addCategory() {
var newCategory = storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
var nav = UINavigationController(rootViewController: newCategory)
popover = UIPopoverController(contentViewController: nav)
popover!.setPopoverContentSize(CGSizeMake(550, 600), animated: true)
popover!.delegate = self
popover!.presentPopoverFromBarButtonItem(self.navigationItem.rightBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}
выход:
![enter image description here]()
Когда я делаю то же самое с помощью UIPopoverPresentationController, я все равно не могу этого сделать. это мой код:
func addCategory() {
var popoverContent = self.storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
var nav = UINavigationController(rootViewController: popoverContent)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
var popover = nav.popoverPresentationController as UIPopoverPresentationController
popover.delegate = self
popover.popoverContentSize = CGSizeMake(1000, 300)
popover.sourceView = self.view
popover.sourceRect = CGRectMake(100,100,0,0)
self.presentViewController(nav, animated: true, completion: nil)
}
Я получаю точно такой же вывод.
Как мне настроить размер моего поповера? Любая помощь будет высоко оценен!
Ответы
Ответ 1
Хорошо, соседка посмотрела на него и поняла:
func addCategory() {
var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
var nav = UINavigationController(rootViewController: popoverContent)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
var popover = nav.popoverPresentationController
popoverContent.preferredContentSize = CGSizeMake(500,600)
popover.delegate = self
popover.sourceView = self.view
popover.sourceRect = CGRectMake(100,100,0,0)
self.presentViewController(nav, animated: true, completion: nil)
}
Вот так.
Вы больше не разговариваете с самим popover, вы говорите с контроллером представления внутри него, чтобы установить размер содержимого, вызвав свойство preferredContentSize
Ответ 2
На самом деле это намного проще. В раскадровке вы должны сделать viewcontroller, который хотите использовать как popover, и создать для него класс viewcontroller, как обычно. Сделайте segue, как показано ниже, из объекта, который вы хотите открыть popover, в этом случае UIBarButton
с именем "Config".
![enter image description here]()
В "контроле просмотра мати" реализуйте метод UIPopoverPresentationControllerDelegate
и делегата:
func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
//do som stuff from the popover
}
Отмените метод prepareForSeque
следующим образом:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//segue for the popover configuration window
if segue.identifier == "yourSegueIdentifierForPopOver" {
if let controller = segue.destinationViewController as? UIViewController {
controller.popoverPresentationController!.delegate = self
controller.preferredContentSize = CGSize(width: 320, height: 186)
}
}
}
И все готово. И теперь вы можете рассматривать popover-представление как любое другое представление, т.е. добавьте поля, а что нет! И вы получите контроллер содержимого с помощью метода popoverPresentationController.presentedViewController
в UIPopoverPresentationController
.
Также на iPhone вам придется перезаписать
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return UIModalPresentationStyle.none
}
Ответ 3
Я нашел полный пример того, как заставить все это работать, чтобы вы всегда могли отображать popover независимо от устройства/ориентации https://github.com/frogcjn/AdaptivePopover_iOS8_Swift.
Ключом является реализация UIAdaptivePresentationControllerDelegate
func adaptivePresentationStyleForPresentationController(PC: UIPresentationController!) -> UIModalPresentationStyle {
// This *forces* a popover to be displayed on the iPhone
return .None
}
Затем продолжите пример выше (из Imagine Digital):
nav.popoverPresentationController!.delegate = implOfUIAPCDelegate
Ответ 4
Swift 2.0
Хорошо, я справился. Взгляни. Создал ViewController в StoryBoard. Связан с классом PopOverViewController.
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)
}
}
См. ViewController:
// ViewController.swift
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
}
}
Примечание. Метод func showPopover (база: UIView) должен быть размещен перед ViewDidLoad. Надеюсь, это поможет!
Ответ 5
В iOS9 UIPopoverController обесценивается. Так что можете использовать приведенный ниже код для версии Objective-C выше iOS9.x,
- (IBAction)onclickPopover:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *viewController = [sb instantiateViewControllerWithIdentifier:@"popover"];
viewController.modalPresentationStyle = UIModalPresentationPopover;
viewController.popoverPresentationController.sourceView = self.popOverBtn;
viewController.popoverPresentationController.sourceRect = self.popOverBtn.bounds;
viewController.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:viewController animated:YES completion:nil]; }
Ответ 6
Здесь я конвертирую "Joris416" Swift Code в Objective-c,
-(void) popoverstart
{
ViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"PopoverView"];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:controller];
nav.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = nav.popoverPresentationController;
controller.preferredContentSize = CGSizeMake(300, 200);
popover.delegate = self;
popover.sourceView = self.view;
popover.sourceRect = CGRectMake(100, 100, 0, 0);
popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:nav animated:YES completion:nil];
}
-(UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller
{
return UIModalPresentationNone;
}
Помните ДОБАВИТЬ
UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate
Ответ 7
Это лучше всего поясняется в блоге iOS8 "День за днем "
Короче говоря, как только вы установили свой modalPresentationStyle для UIViewController в .Popover, вы можете получить UIPopoverPresentationClass (новый класс iOS8) через свойство popoverPresentationController контроллера.
Ответ 8
мои два цента для xcode 9.1/swift 4.
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
override func viewDidLoad(){
super.viewDidLoad()
let when = DispatchTime.now() + 0.5
DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
// to test after 05.secs... :)
self.showPopover(base: self.view)
})
}
func showPopover(base: UIView) {
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "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.present(navController, animated: true, completion: nil)
}
}
}
@IBAction func onShow(sender: UIButton){
self.showPopover(base: sender)
}
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle{
return .none
}
и эксперимент в:
func adaptivePresentationStyle...
return .popover
или: вернуть .pageSheet.... и так далее..
Ответ 9
Я сделал версию быстрого ответа Imagine Digitals Objective-C выше. Я не думаю, что я пропустил что-либо, поскольку, похоже, он работает под предварительным тестированием, если вы заметили что-то, дайте мне знать, и я обновлю его.
-(void) presentPopover
{
YourViewController* popoverContent = [[YourViewController alloc] init]; //this will be a subclass of UIViewController
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:popoverContent];
nav.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popover = nav.popoverPresentationController;
popoverContent.preferredContentSize = CGSizeMake(500,600);
popover.delegate = self;
popover.sourceRect = CGRectMake(100,100,0,0); //I actually used popover.barButtonItem = self.myBarButton;
[self presentViewController:nav animated:YES completion:nil];
}
Ответ 10
Внедрите UIAdaptivePresentationControllerDelegate в свой Viewcontroller.
Затем добавьте:
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle{
return .none
}
Ответ 11
Ниже приведено довольно полное руководство по настройке и представлению всплывающих окон. https://www.appcoda.com/presentation-controllers-tutorial/
Таким образом, жизнеспособная реализация (с некоторыми обновлениями исходного синтаксиса статьи для Swift 4.2), которая затем будет вызываться из другого места, будет выглядеть примерно так:
func showPopover(ofViewController popoverViewController: UIViewController, originView: UIView) {
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
if let popoverController = popoverViewController.popoverPresentationController {
popoverController.delegate = self
popoverController.sourceView = originView
popoverController.sourceRect = originView.bounds
popoverController.permittedArrowDirections = UIPopoverArrowDirection.any
}
self.present(popoverViewController, animated: true)
}
Многое из этого уже было рассмотрено в ответе @mmc, но статья помогает объяснить некоторые из используемых элементов кода, а также показать, как его можно расширить.
В нем также содержится много дополнительной информации об использовании делегирования для обработки стиля презентации для iPhone и iPad, а также для разрешения отклонения всплывающего окна, если оно отображается в полноэкранном режиме. Опять же, обновлено для Swift 4.2:
func adaptivePresentationStyle(for: UIPresentationController) -> UIModalPresentationStyle {
//return UIModalPresentationStyle.fullScreen
return UIModalPresentationStyle.none
}
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
if traitCollection.horizontalSizeClass == .compact {
return UIModalPresentationStyle.none
//return UIModalPresentationStyle.fullScreen
}
//return UIModalPresentationStyle.fullScreen
return UIModalPresentationStyle.none
}
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
switch style {
case .fullScreen:
let navigationController = UINavigationController(rootViewController: controller.presentedViewController)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(doneWithPopover))
navigationController.topViewController?.navigationItem.rightBarButtonItem = doneButton
return navigationController
default:
return controller.presentedViewController
}
}
// As of Swift 4, functions used in selectors must be declared as @objc
@objc private func doneWithPopover() {
self.dismiss(animated: true, completion: nil)
}
Надеюсь это поможет.
Ответ 12
Для тех, кто хочет учиться!
Я создал проект с открытым исходным кодом для тех, кто хочет изучать и использовать представление Popover для любой цели. Вы можете найти проект здесь. https://github.com/tryWabbit/KTListPopup
![KTListNewResize]()
Ответ 13
Swift 3:
В моем случае, априори, есть знание только о том, что базовый UIViewController является TextViewController (мое имя для UIViewController, которое мне нужно заполнить), что он может быть popOverPresentationController и что он содержит NSMutableAttributedString.
Это вся информация, необходимая для правильного размера popOverPresentationController, с использованием размера NSMutableAttributedString, а затем установки размера UIViewController на размер отправляемой строки. Я создаю NSMutableAttributedString, устанавливаю его содержимое с помощью метода под названием "createStats()".
Обратите внимание, что мне нужно установить базовый предпочтительный размер содержимого UIViewController, поэтому я использую: tvc.preferredContentSize, чтобы установить его. UIViewController называется "tvc". Я использую tvc.preferredContentSize = CGSizeFromString (String (описывающий: myCreatedAttributedMutableString)).
Мой popOverPresentationController (который является UIViewController) имеет textView. Поэтому в раскадровке я установил textView как "Attributed". введите здесь описание изображения
TextView имеет строку (называемую "операциями" ), которая доставляется ей с помощью segue. Эта строка ( "операции" ) - это все содержимое, которое будет отображаться при появлении popover.
Итак, мое решение состоит в том, чтобы использовать следующее в подготовке (для segue:...)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let tvc = segue.destination as? TextViewController {
if let ppc = tvc.popoverPresentationController {
ppc.delegate = self
}
let returnStatsStr: NSMutableAttributedString = createStats()
let myCreatedAttributedMutableString = NSMutableAttributedString.init()
myCreatedAttributedMutableString.append(returnStatsStr)
tvc.operations = myCreatedAttributedMutableString
tvc.preferredContentSize = CGSizeFromString(String(describing: myCreatedAttributedMutableString))
}
}
Вот как он появляется, когда он появляется.
введите здесь описание изображения