5

Chcę pokazać modalny UIViewController z niestandardową ramką na iPadzie, wyśrodkowaną nad rodzicielskim kontrolerem widoku.Pokaż kontroler widoku modalnego z niestandardową ramką na iPadzie

Próbowałem użyć arkusza formularza, ale o ile wiem, efekt ramki i cienia nie może zostać zmieniony.

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

Próbowałem też za pomocą popover ale o ile wiem, ani nie mogę wyśrodkować go lub nie mogę ukryć strzałkę.

Czy istnieje inny sposób pokazywania kontrolerów widoku modalnego? Czy jest możliwe rozwiązanie tego problemu za pomocą arkuszy formularzy lub popover?

+1

Możesz pokazać coś w stylu popover, gdziekolwiek chcesz za pomocą presentPopoverFromRect, a nawet sprawić, żeby zachowywał się modalnie, ale jedyną wadą jest to, że nie ma sposobu na ukrycie strzałki. – Anna

Odpowiedz

4

Nie ma oficjalny sposób, aby to zrobić, jednak można uzyskać pożądane zachowanie pisząc własny widok, który utrzymuje odwołanie lub pełnomocnika do współdziałania z kontrolerem widoku przedstawianie i dodanie go do hierarchii widoku. Aby naprawdę uzyskać wrażenie modalne, można również umieścić przezroczystą nakładkę na kontrolerze prezentacji tuż poniżej widoku "modalnego". Zrobiłem to w wielu aplikacjach i zazwyczaj działa świetnie. Najprawdopodobniej będziesz musiał utworzyć niestandardowy widok nakładki, aby można było przechwycić dotknięcia i bardziej elegancko ożywić jego prezentację.

Moja przezroczysta nakładka jest zwykle coś takiego:

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

Mój widok niestandardowy modalna jest zazwyczaj coś takiego:

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

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

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

moim zdaniem przedstawianie kontrolera I zazwyczaj należy wykonać następujące czynności:

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

Korzystanie z delegatów zdefiniowanych na dwóch zajęciach daje mi prawie otwarty dostęp do manipulowania moim kontrolerem prezentacji, a także do mojej prezentacji i zwolnienia zgodnie z życzeniem. Jedynym minusem tego jest użycie go w widoku z pasem nawigacyjnym, ponieważ granice widoku kontrolera prezentującego nie zawierają granic paska nawigacyjnego pozostawiając go otwartego do interakcji, istnieją sposoby na obejście tego, ale nie na ich temat są bardzo ładne (dodanie do widoku kontrolera nawigacyjnego jest jedną z opcji).

+0

Jaki jest cel '- (void) performSelectorOnDelegate: (SEL) selektor;' w 'ModalViewDelegate'? –

1

To może nie w pełni odpowiedzieć na twoje pytanie. Ale nazywam następujący kod z rightbuttonitem na kontrolerze nawigacyjnym, który wcześniej umieściłem na górze szczegółowego widoku kontrolera splitviewcontroller.

Ten modalny widok obejmuje cały ekran. Czy chciałbyś na przykład wyświetlić widok szczegółów tylko wtedy, gdy został wywołany w 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

Korzystam z poniższej metody, aby utworzyć kontroler widoku modalnego o dowolnym rozmiarze wyśrodkowanym na ekranie. Jeśli chcesz, możesz go zmienić na centrum w nadrzędnym kontrolerze widoku. Działa to z scenorysu, więc zamiast tego możesz wysłać kontroler widoku jako argument. Ale poza tym robi to, czego potrzebujesz.

UWAGA: Zauważyłem, że jeśli spróbujesz pokazać inny modalny nad nim, powróci on do pierwotnego rozmiaru.

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

Jeśli to jedyna rzecz, którą chcesz, działa dobrze. Ale znalazłem to, że wdrożenie przez Apple modalnych kontrolerów widoku jest trochę nieproduktywne, ponieważ nie możesz uzyskać dostępu do jego podstawowych części i nie możesz ich w pełni animować. Przydatne, jeśli chcesz mieć własne przejścia.

Nie mieści się również w kategorii kontrolera widoku podrzędnego, ponieważ znajduje się nad wszystkimi pozostałymi widokami w oknie.

+0

Bardzo mi to pomogło. Dzięki. –

+0

+1 Próbowałem zmienić rozmiar modałów na wieki, ale żadne z rozwiązań StackOverflow nie były pomocne. Albo nie zmieniło/poprawnie wyśrodkowało widoku, albo nie działało ze wszystkimi elementami przejściowymi. To rozwiązanie jest PERFECT! –

+0

Aktualizacja IOS 7 poniżej i może usunąć problem zrodzonego problemu potomka, o którym mowa powyżej – gjpc

1

wolę odpowiedź Fabio-Oliveira, ale wymaga pewnych korekt, aby pozwolić mu pracować na iOS 7 Multi środowiska Temat:

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

Teraz umieścić centrowania kodu w docelowym VC więc nowy wątek działa :

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

Och Tak, jeśli wspieraniu osób piękny iOS 5 iPad 1-ki, z pewnością poinformujemy obrót tarczy vc:

- (BOOL)shouldAutorotateToInterfaceOrientation: 
         (UIInterfaceOrientation)interfaceOrientation 
{ 
    return YES; 
} 
+0

hi @gjpc, użyłem twojego kodu i działa dobrze, ale kiedy się pojawi, mam na myśli to, że kiedy modalView jest prezentowany, otwiera się od rogu i oddala w kierunku środka. Znalazłeś to. – Ranjit

+0

@Ranjit Używam iModalTransitionStyle: UIModalTransitionStyleCoverVertical]; i pojawiają się od dołu i przechodzą przez dno – gjpc

+0

Próbowałem używać ModalTransitionStyle: UIModalTransitionStyleCoverVertical] ;, ale modalny pojawia się od dolnego rogu i kiedy odrzucam, odrzuca w środku dołu. – Ranjit

1

W moim przypadku nadpisanie numeru viewWillLayoutSubviews rozwiązało problem. więcej było potrzebne, aby zmienić położenie i granice ModalViewController

- (void)viewWillLayoutSubviews { 
     [super viewWillLayoutSubviews]; 

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

Nic.

+0

To działało dla mnie, dopóki aktywność użytkownika nie przyniosła klawiatury iPada na ekranie, w którym to punkcie modal cofnął się do poprzedniej pozycji. –

Powiązane problemy