Показать модальный контроллер вида с пользовательской рамкой в ​​iPad - PullRequest
5 голосов
/ 01 ноября 2010

Я хочу показать модальное UIViewController с настраиваемой рамкой в ​​iPad, центрированной поверх родительского контроллера просмотра.

Я пытался использовать форму, но насколько я знаю, эффект рамки и тениизменить нельзя.

vc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:cv animated:YES];

Я также пытался использовать поповер, но насколько я знаю, я не могу отцентрировать его или не могу скрыть стрелку.

IsЕсть ли другой способ показать модальные контроллеры представления?Можно ли решить эту проблему с помощью форм-листов или всплывающих окон?

Ответы [ 5 ]

6 голосов
/ 15 августа 2012

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

ПРИМЕЧАНИЕ. Я обнаружил, что если вы попытаетесь показать другой модал поверх этого, он вернется к исходному размеру.

- (UIViewController *) presentModalViewControllerWithIdentifier:(NSString *)identifier 
                                                        andSize:(CGSize)size 
                                        andModalTransitionStyle:(UIModalTransitionStyle)modalTransitionStyle {
    UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];


    viewController.modalPresentationStyle = UIModalPresentationPageSheet;
    viewController.modalTransitionStyle = modalTransitionStyle;
    [self presentModalViewController:viewController animated:YES];
    viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin | 
    UIViewAutoresizingFlexibleLeftMargin | 
    UIViewAutoresizingFlexibleRightMargin;    
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    viewController.view.superview.frame = CGRectMake(0, 0, size.width, size.height);
    CGPoint center = CGPointMake(CGRectGetMidX(screenBounds), CGRectGetMidY(screenBounds));
    viewController.view.superview.center = UIDeviceOrientationIsPortrait(self.interfaceOrientation) ? center : CGPointMake(center.y, center.x);

    return viewController;
}

Если это единственное, что вам нужно, то оно работает нормально. Но что я обнаружил, так это то, что реализация контроллеров модальных представлений Apple немного контрпродуктивна, поскольку вы не можете получить доступ ни к одной из его базовых частей и не можете полностью их анимировать. Полезно, если вы хотите иметь свои собственные переходы.

И он не попадает также в категорию дочерних контроллеров представления, поскольку он стоит над всеми другими представлениями в окне.

4 голосов
/ 28 января 2012

Официального способа сделать это не существует, однако вы можете получить желаемое поведение, написав пользовательское представление, в котором хранится ссылка или делегат для взаимодействия с представляемым контроллером представления и добавляя его в иерархию представления.Чтобы по-настоящему почувствовать модальность, вы также можете разместить прозрачный оверлей над контроллером представления чуть ниже вашего «модального» вида.Я сделал это во многих приложениях, и это обычно работает отлично.Скорее всего, вам потребуется создать пользовательский вид наложения, чтобы вы могли перехватывать прикосновения и более элегантно анимировать его презентацию.

Мое прозрачное наложение обычно выглядит примерно так:

@protocol TransparentOverlayDelegate <NSObject>

@optional
- (void)transparentOverlayWillDismiss:(TransparentOverlay *)backgroundTouch;
- (void)transparentOverlayDidDismiss:(TransparentOverlay *)backgroundTouch;
@end


@interface TransparentOverlay : UIView {

    id<TransparentOverlayDelegate> _delegate;
    UIView *_contentView;
    CGFloat _pAlpha;
}

@property(nonatomic, assign) id<TransparentOverlayDelegate> delegate;
@property(nonatomic, retain) UIView *contentView;
@property(nonatomic, assign) CGFloat pAlpha;

- (void)presentTransparentOverlayInView:(UIView *)view;
- (void)dismissTransparentOverlay:(BOOL)animated;

Мой пользовательский модальный видобычно выглядит примерно так:

@protocol ModalViewDelegate <NSObject>
- (void)performSelectorOnDelegate:(SEL)selector;
@end

@interface ModalView : UIView {
    id<ModalViewDelegate> _delegate;
}

@property(nonatomic, assign) id<ModalViewDelegate> delegate;

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

- (void)presentModalController {
    TransparentOverlay *to = [[[TransparentOverlay alloc] initWithFrame:self.view.bounds] autorelease];
    to.delegate = self;

    ModalView *mv = [[ModalView alloc] initWithFrame:CGRectMake(500, 500, 300, 300)];
    mv.delegate = self;

    to.contentView = mv;
    [mv release];

    [to presentTransparentOverlayInView:self.view]; 
}

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

1 голос
/ 31 июля 2014

В моем случае, переопределение viewWillLayoutSubviews добилось цели.

- (void)viewWillLayoutSubviews {
        [super viewWillLayoutSubviews];

    self.view.superview.frame = CGRectMake(100.f, 100.f, <width>, <height>); 
}

Больше ничего не нужно было для изменения положения и границ ModalViewController.

1 голос
/ 14 октября 2013

Я предпочитаю ответ fabio-oliveira, но для его работы в многопоточной среде IOS 7 требуется некоторая корректировка:

- (UIViewController *)presentModalViewControllerWithId:(NSString *)identifier
                                           andSize:(CGSize)size
                           andModalTransitionStyle:(UIModalTransitionStyle)style
{
    UIViewController *viewController = 
            [self.storyboard instantiateViewControllerWithIdentifier:identifier];

    viewController.modalPresentationStyle = UIModalPresentationPageSheet;
    viewController.modalTransitionStyle = style;

    [self presentViewController:viewController animated:YES completion:nil];

    viewController.view.superview.autoresizingMask = 
        UIViewAutoresizingFlexibleTopMargin    |
        UIViewAutoresizingFlexibleBottomMargin | 
        UIViewAutoresizingFlexibleLeftMargin   | 
        UIViewAutoresizingFlexibleRightMargin;

    viewController.view.superview.frame = 
                   CGRectMake(0, 0, size.width, size.height);

   return viewController;
}

Теперь поместите центрирующий код в целевой VC, чтобы новый поток работал:

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    CGPoint center = CGPointMake(CGRectGetMidX(screenBounds),
                                 CGRectGetMidY(screenBounds));

    self.view.superview.center =
    UIDeviceOrientationIsPortrait(self.interfaceOrientation) ? 
                                       center : CGPointMake(center.y, center.x);
}

О, да, если вы поддерживаете эти прекрасные IOS 5 iPad 1, убедитесь, что целевой vc вращается:

- (BOOL)shouldAutorotateToInterfaceOrientation:
                         (UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}
1 голос
/ 11 февраля 2011

Это может не полностью ответить на ваш вопрос.Но я вызываю следующий код из правой кнопки на навигационном контроллере, который я ранее поместил в верхней части подробного представления контроллера splitview.

Этот модальный вид охватывает весь экран.Например, хотите ли вы охватить подробный вид, только если он вызван в контроллере detailview?

- (void)aboutAction {

About *about = [[About alloc] init];
UINavigationController *nav1 = [[UINavigationController alloc]initWithRootViewController:about];
[about release];
nav1.navigationBar.barStyle = UIBarStyleBlackOpaque;
nav1.modalPresentationStyle = UIModalPresentationFullScreen;
nav1.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:nav1 animated:YES ];
[nav1 release];

}
...