2012-04-11 87 views
4

在iPad上,我使用modalPresentationStyle UIModalPresentationPageSheet顯示模態視圖控制器。此視圖控制器使用modalPresentationStyle UIModalPresentationFormSheet顯示另一個模式視圖控制器。在模態頁面上顯示模態表單

因此,由於表單小於頁面表單,所以用戶看到背景視圖控制器,頁面表單和表單表單全部在彼此之上。頁面的表示讓背景變暗,以至於無法與之互動。但是,表單不會在iOS 5中調暗頁面表,以便用戶仍然可以與下面的頁面頁進行交互。但是我也希望頁面變暗,以便用戶在能夠再次與頁面交互之前關閉模式表單。

在iOS 4上,這是默認行爲,但在iOS 5上我找不到實現此目的的方法。你有什麼建議嗎?

+0

我在iOS 5中注意到了這一點,並且在iOS 6中看到了同樣的問題。 – arlomedia 2012-10-19 23:43:57

+0

我剛剛提交了這個錯誤報告12540692. – arlomedia 2012-10-20 00:37:21

回答

2

我相信這是iOS5中的一個錯誤。我已經做了一些試驗,展示其他模態的模態視圖控制器,看起來第二個模態從不會調暗下面的屏幕。我甚至設置了一個測試項目,允許你從對方發起無盡的模態,並且看起來每個其他模態都不會像預期的那樣調暗或阻擋觸摸。

UIWindow子視圖的快速NSLog向​​我們顯示,當正在添加陰影時,dimmingView不適用。我正在努力展示我自己的調光視圖。當我找到方法時會更新這個答案。

Window Subviews: (
    "<UILayoutContainerView: 0xf63e3c0; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf645640>>", 
    "<UIDimmingView: 0xf683990; frame = (0 0; 768 1024); opaque = NO; layer = <CALayer: 0xf6836d0>>", 
    "<UIDropShadowView: 0xf683130; frame = (64 64; 640 896); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf6831c0>>", 
    "<UIDropShadowView: 0x292110; frame = (74 242; 620 540); transform = [0, 1, -1, 0, 0, 0]; autoresize = LM+RM+TM+BM; layer = <CALayer: 0x292150>>" 
) 

解決方法二: 所以在我的動畫看最終的解決方案。 此外,我不得不考慮我的第一個解決方案,它的技術可能性會使蘋果產生排斥並導致拒絕,因爲UID預覽沒有記錄,我們「接觸它」。我添加了一個背景顏色的UIView我們想要我的viewController的alpha。然後當我呈現模態時動畫,並在第二個模態的代表被調用時反轉動畫。它對我來說很不錯。也許一些時機和alpha調整,以得到它只是正確的,但其工作,並看起來不錯。

- (void)viewDidLoad 
{ 
    dim = [[UIView alloc] init]; 
    [dim setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.35]]; 
    [dim setAlpha:0.0]; 
    [dim setUserInteractionEnabled:NO]; 
    [self.view addSubview:dim]; 
} 

- (void)presentModal 
{ 
    [self.view bringSubviewToFront:dim]; 
    [dim setFrame:self.view.frame]; 
    [UIView animateWithDuration:0.25 animations:^{ 
     [dim setAlpha:1.0]; 
    }]; 
} 

- (void)modalDelegateFinished 
{ 
    [UIView animateWithDuration:0.25 animations:^{ 
     [dim setAlpha:0.0]; 
    }]; 
} 

解決方法一:

好吧,所以這個工作,但它並不像動畫片,我想。然而,它確實重用了已有的東西,所以可能還有一個好處。

- (void)viewDidAppear:(BOOL)animated 
{ 
    // Add a gesture to dismiss the view if tapped outside. 
    UIGesture *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedOutsideView:)]; 
    [gesture setNumberOfTapsRequired:1]; 
    [gesture setCancelsTouchesInView:NO]; 
    [self.view.window addGestureRecognizer:gesture]; 

    // Move the dimmingview to just below the dropshadow. 
    UIView *dim = [self.view.window.subviews objectAtIndex:1]; 
    [self.view.window insertSubview:dim atIndex:2]; 
} 

- (void)tappedOutsideView:(UITapGestureRecognizer *)sender 
{ 
    if (sender.state == UIGestureRecognizerStateEnded) { 
     CGPoint location = [sender locationInView:nil]; 

     if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) { 
      // remove the gesture on the window 
      [self.view.window removeGestureRecognizer:sender]; 

      // Move the dimmingview back where it belongs 
      UIView *dim = [self.view.window.subviews objectAtIndex:2]; 
      [self.view.window insertSubview:dim atIndex:1]; 
     } 
    } 
} 

此外作爲一個失敗保險,它可能是一個好主意,在viewDidDisappear相同的東西。我完成的按鈕調用tappedOutside視圖,所以我知道手勢和dimmingView總是正確的。但如果你沒有這樣做,你可以把它放在viewDidDisappear中。

- (void)viewDidDisappear:(BOOL)animated 
{ 
    // remove the gesture on the window 
    for (UIGestureRecognizer *gesture in self.view.window.gestureRecognizers) { 
     [self.view.window removeGestureRecognizer:gesture]; 
    } 

    // Move the dimmingview back where it belongs 
    UIView *dim = [self.view.window.subviews objectAtIndex:2]; 
    [self.view.window insertSubview:dim atIndex:1]; 
} 
+0

這是我的expraience。現在,我只是不在頁面頂部展示表單並在我的應用中隨處使用頁面表。 – Tom 2012-04-23 12:51:42

+0

我已經設置了窗口手勢,因此在模態之外點擊總是會導致它解散。所以,因爲觸摸不能通過我的手勢,他們可以通過背景模態。 然而,從視覺上來說,它會很好地變暗。我可能在一個系統上工作,除了模態之外,將窗口中的所有內容調暗。 – 2012-04-23 14:51:05

+0

更新了我的答案。我找到了兩個解決方案。比另一個更加動畫和安全。 :) – 2012-04-23 15:59:32

0

它看起來像一個iOS的錯誤。仍然在iOS7中。

以下是我所做的工作(iOS7測試)。有趣的是,在模態上呈現模態不會暗淡主持人,但會在這些模式之上呈現第三種模態。

知道這一點之後,我們可以在呈現實際表單模式之前​​呈現一個虛擬物體。這涉及最少的代碼,並且在技術上符合一般的iOS設計模式。所以未來爆炸的風險應該是最小的。

首先呈現形式片:

- (void)presentFormSheetModalOverThePageSheetModal 
{ 
    //get the controller I'm trying to present and stick it in a nav controller - as usual 
    UIViewController *myModalController = [UIViewController new]; 
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myModalController]; 
    navController.modalPresentationStyle = UIModalPresentationFormSheet; 

    //create an intermediate controller that will be presented first 
    UIViewController *intermediateController = [UIViewController new]; 
    intermediateController.modalPresentationStyle = UIModalPresentationCurrentContext; 
    intermediateController.view.backgroundColor = self.view.backgroundColor; 

    //create a snapshot of self (presenting controller) 
    UIView *navBar = [self.navigationController.navigationBar snapshotViewAfterScreenUpdates:YES]; 
    UIView *mainView = [self.view snapshotViewAfterScreenUpdates:YES]; 
    mainView.center = CGPointMake(mainView.center.x, mainView.center.y + navBar.frame.size.height); 
    [intermediateController.view addSubview:navBar]; 
    [intermediateController.view addSubview:mainView]; 

    //two step presentation 
    [self presentViewController:intermediateController animated:NO completion:^{ 
     [intermediateController presentViewController:navController animated:YES completion:nil]; 
    }]; 
} 

然後,當它的時間以關閉(從所呈現的模態):

- (void)dismissMySelf 
{ 
    //again - two step process to dismiss the this controller and the intermediate controller 
    UIViewController *originalPresenter = self.presentingViewController.presentingViewController; 
    [self.presentingViewController dismissViewControllerAnimated:YES completion:^{ 
     [originalPresenter dismissViewControllerAnimated:NO completion:nil]; 
    }]; 
} 

我不得不調整它,因爲在快照是一個靜態圖像並沒有處理旋轉,但總的來說,它對我很好。希望能幫助到你。