iPad нестандартного размера контроллера модального вида - PullRequest
54 голосов
/ 21 июля 2010

У меня есть пара модальных контроллеров представления определенного размера.Я стараюсь избегать использования пользовательских представлений (создание полноэкранного черного полупрозрачного наложения поверх текущего представления, добавление модального представления поверх этого представления, создание анимации и т. Д.) Для его представления, поскольку не существует modalPresentationStyle, который бы соответствовал размеру моегоконтроллеры.

Сейчас я использую UIModalPresentationPageSheet, но мой вид меньше по высоте, и у меня появляется ужасное пустое пространство

Желаемая презентация

 _______________
|    _______    |
|   |       |   |
|   |  MyVC |   |
|   |       |   |
|    -------    |
 --------------- 

Фактическое представление

 _______________
|   |       |   |
|   |  MyVC |   |
|   |       |   |
|   |-------|   |
|   | blank |   |
 ---------------    

Если я использую UIModalPresentationFormSheet, контейнер будет меньше по ширине.

Я пытаюсь выяснить, как это сделать, но я нене знаю, возможно ли это.Каково решение проблемы представления модального VC, меньшего чем любой из стилей представления?Единственное решение состоит в том, чтобы устроить «пользовательский модальный контроллер движка»?Popovers не соответствует моим требованиям к дизайну: (

Ответы [ 13 ]

84 голосов
/ 23 января 2013

Как и у некоторых других пользователей здесь, у меня также была проблема с тем, что происхождение контроллера модального представления было неправильным. После некоторых экспериментов я нашел решение, которое работало на меня:

- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];   
    self.view.superview.bounds = CGRectMake(0, 0, <width>, <height>);
}
35 голосов
/ 02 августа 2010

Я получил следующий результат ( текст ссылки ), используя:

self.modalPresentationStyle = UIModalPresentationFormSheet;

и представив его как модальный контроллер вида. Дайте мне знать, если вам понадобится дополнительная помощь.

24 голосов
/ 22 сентября 2014

Все эти ответы не будут работать на ios8 SDK.

Это будет работать:

AboutViewController * _aboutViewController = [[AboutViewController alloc] init];
    _aboutViewController.modalPresentationStyle = UIModalPresentationFormSheet;
    if(IS_IOS8)
    {
        _aboutViewController.preferredContentSize = CGSizeMake(300, 300);
    }
    [self presentViewController:_aboutViewController animated:YES completion:nil];

В 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)

В iOS 8 вы также можете использовать UIPresentationController, который дает вам больше возможностей для настройки.

19 голосов
/ 12 ноября 2012

У меня была проблема с получением модальности нестандартного размера по центру, пока я не выяснил, что было изначально установлено для ViewController.view.superview.frame. Он определяется на основе типа UIModalPresentation. superview.center даже не требуется (насколько показывает мой тест).

Кроме того, я установил координаты динамически, используя [UIScreen mainScreen].applicationFrame, пока поддерживаю только альбомную ориентацию. Вы должны выполнить условную проверку для поддержки как портретной, так и альбомной ориентации, перевернув значения X / Y и Высота / Ширина.

Вот мое первое рабочее решение для 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
                                                                    );

А потом я посмотрел на предыдущий ответ и повернул лицо ладонью. Немного сократил мое решение, заменив последнюю строку на:

ViewController.view.superview.bounds = CGRectMake(0, 0, 320, 320);

РЕДАКТИРОВАТЬ для окончательного решения и замечаний.

18 голосов
/ 13 апреля 2012

Лучший способ сделать это - изменить свойство границ в суперпредставлении представления, представляемого внутри формы.Когда вы представляете представление модально, представленное представление внедряется в другое представление.

Необходимо установить для свойства bounds суперпредставления тот же прямоугольник, что и для границ представления.Сначала добавьте в свой класс личный ивар:

@implementation MySpecialFormsheet {
    CGRect _realBounds;
} 

Лучше всего сделать это в viewWillAppear:.Добавьте следующий код в контроллер представления, который представлен модально:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.view.superview.bounds = _realBounds;
}

Вам необходимо кэшировать _realBounds в вашем методе viewDidLoad:

- (void)viewDidLoad {
    _realBounds = self.view.bounds;
    [super viewDidLoad];
}
7 голосов
/ 24 сентября 2014

Это мое решение для представления НЕ с автоматическим размещением (никогда не использовалось с авто-расположением) и совместимым с iOS 7 и iOS 8.

Сначала обязательно вызовите модальное представление следующим образом:

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]; 

В iOS 8 установите предпочитаемый размер содержимого в методе viewDidLoad модального представления.

- (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
}

Это работает ТАКЖЕ, когда модальное представление должно отображать клавиатуру на iPad .

В предыдущих версиях iOS 8 вы должны устанавливать границы после вызова 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 
6 голосов
/ 11 октября 2012

даже для уменьшения высоты и ширины листа формата вы можете использовать

[self.view.superview setBounds:CGRectMake(0, 0, 450, 480)];
5 голосов
/ 05 декабря 2013

Подходы, описанные выше, должны быть настроены для 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;
    }
}

(Этот код также работает на iOS6.)

4 голосов
/ 21 января 2014

Даже я довольно долго боролся с той же проблемой. После нескольких попыток ответить на многие из приведенных здесь, я нашел решение, которое мне очень помогло.

Вот код при представлении контроллера представления.

    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

В xib (если вы его используете) в разделе «Симулированные метрики» выберите размер «Свободная форма».

Помимо этого вам необходимо написать приведенный ниже код в представленном вами контроллере представления (т.е. в этом примере SomeViewController)

- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want

}

Этот код также работает для iOS 7

3 голосов
/ 08 февраля 2011

Одним из решений является использование UIModalPresentationPageSheet для представления листа страницы, а затем немедленно изменить размер модального представления.Это полностью объяснено в этом ответе на другой вопрос .

...