5

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

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

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

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

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

+1

Вы можете как-то показать popover везде, где вам нравится, с помощью presentPopoverFromRect и даже заставить его вести себя модально, но только недостаток - нет способа спрятать стрелку. – Anna

ответ

4

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

Моя прозрачная накладка, как правило, что-то вроде этого:

@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, оставляя его открытым для взаимодействия, есть способы обойти это, но не из них очень хороши (добавление к виду контроллера навигации - один из вариантов).

+0

Какова цель '- (void) выполнитьSelectorOnDelegate: (SEL) селектор;' в 'ModalViewDelegate'? –

1

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

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

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

} 
6

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

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

- (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 является немного контрпродуктивной, поскольку вы не можете получить доступ к каким-либо ее основным частям, и поэтому вы не можете полностью их оживить. Полезно, если вы хотите иметь свои собственные переходы.

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

+0

Это очень помогло мне. Благодарю. –

+0

+1 Я пытался изменить размеры модалов целую вечность, но ни одно из решений на StackOverflow не помогло. Это либо не изменило размер/центр представления правильно, либо не работало со всеми переходами. Это решение СОВЕРШЕННО! –

+0

Обновление IOS 7 ниже и оно может удалить проблему с ребенком, вызванную вирусом vc, упомянутую выше – gjpc

1

Я предпочитаю ответ Fabio-Оливейра, но это требует некоторой корректировки, чтобы позволить ему работать на многопользовательской среде потоков 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; 
} 
+0

hi @gjpc, я использовал ваш код, и он отлично работает, но когда он появляется, я имею в виду, когда представлен modalView, он открывается из угла и отклоняется к центру. Вы нашли это. – Ranjit

+0

@Ranjit Я использую andModalTransitionStyle: UIModalTransitionStyleCoverVertical]; и они появляются снизу и уходят через дно. – gjpc

+0

Я пробовал использовать ModalTransitionStyle: UIModalTransitionStyleCoverVertical] ;, Но модаль появляется из нижнего угла, и когда я отклоняю его, он отклоняется в центре дна. – Ranjit

1

В моем случае, переопределение viewWillLayoutSubviews сделал трюк.

- (void)viewWillLayoutSubviews { 
     [super viewWillLayoutSubviews]; 

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

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

+0

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

 Смежные вопросы

  • Нет связанных вопросов^_^