2017-10-10 285 views
4

請考慮以下事項:我製作了一個可重用的UIView子類,它具有背景,並在其子視圖中列出了一些內容。作爲負責任的開發商,我,我已經根據其安全區域對齊視圖的子視圖,這樣它會自動插頁其內容在必要時(例如在iPhone上X):iOS 11安全區與UIView動畫

center vs bottom

好極了!當內部視圖位於安全區域內時,內部視圖會邊對邊,並且在內容視圖從安全區域懸掛出來時將其內容從底部插入。

現在讓我們假設最初的視圖應該在屏幕外,但是當用戶在我的應用程序的某個地方點擊時,我希望我的視圖在屏幕中心生成動畫,並且它應該在第二次點擊時動畫化。讓我們實現這樣的:

@implementation ViewController { 
    UIView* _view; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(animate:)]]; 
} 

- (void)animate:(UITapGestureRecognizer*)sender { 
    if (_view == nil) { 
     _view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
     _view.backgroundColor = UIColor.redColor; 

     UIView* innerView = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 90, 90)]; 
     innerView.translatesAutoresizingMaskIntoConstraints = NO; 
     innerView.backgroundColor = UIColor.blueColor; 

     [_view addSubview:innerView]; 
     [_view addConstraints:@[[_view.safeAreaLayoutGuide.topAnchor constraintEqualToAnchor:innerView.topAnchor constant:-5], 
           [_view.safeAreaLayoutGuide.rightAnchor constraintEqualToAnchor:innerView.rightAnchor constant:5], 
           [_view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:innerView.bottomAnchor constant:5], 
           [_view.safeAreaLayoutGuide.leftAnchor constraintEqualToAnchor:innerView.leftAnchor constant:-5]]]; 

     _view.center = CGPointMake(self.view.bounds.size.width/2, 
            self.view.bounds.size.height + _view.bounds.size.height/2); 
     [self.view addSubview:_view]; 
     [UIView animateWithDuration:1 animations:^{ 
      _view.center = CGPointMake(self.view.bounds.size.width/2, 
             self.view.bounds.size.height/2); 
     }]; 
    } else { 
     [UIView animateWithDuration:1 animations:^{ 
      _view.center = CGPointMake(self.view.bounds.size.width/2, 
             self.view.bounds.size.height + _view.bounds.size.height/2); 
     } completion:^(BOOL finished) { 
      [_view removeFromSuperview]; 
      _view = nil; 
     }]; 
    } 
} 

@end 

所以,現在如果我們啓動應用程序,然後點擊屏幕上,出現這種情況:

animate in

到目前爲止好。然而,這是當我們再次點擊它會發生什麼:

animate out

正如你可以看到,即使視圖進入完全的上海華盈的範圍之外,在安全區插圖仍然可以設置,就好像是在它的超級觀點的底部。

我們可以通過在視圖被動畫化的動畫塊中調用[self.view layoutIfNeeded]來減少效果,但它不能消除問題 - 底部空間只會以動畫方式增長而不是突然擴展:

better, but still bad

這仍然是不適合我接受。我希望它滑出來,就像它滑進來一樣,每邊5pt填充。

有沒有一種方法可以實現這個功能,而不會在我的視圖中添加像shouldAlignContentToSafeAreashouldAlignContentToBounds這樣的標誌?

我只是希望它會自動工作,但工作正確 ...

+1

100%同意這是意外的行爲,並喜歡它似乎違背了safeAreaLayoutGuide文檔「,如果視圖當前沒有安裝在視圖層次結構中,或者屏幕上還不可見,則佈局引導邊與視圖的邊相同。」使用你的例子,並且簡單地將_view放在視圖邊界之外而沒有動畫,我可以看到safeAreaLayoutGuide的底部指南仍然是34. –

回答

0

太簡單的解決方案。試試這個,看看(等於動畫視圖中心內查看設置中心 - innerView.center = animatingView.center;

@interface ViewController() { 

    UIView* animatingView; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    [self setupAnimate]; 
} 

- (void)setupAnimate { 

    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(animate:)]]; 
} 

- (void)animate:(UITapGestureRecognizer*)sender { 
    if (animatingView == nil) { 
     animatingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
     animatingView.backgroundColor = UIColor.redColor; 

     UIView* innerView = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 90, 90)]; 
     innerView.translatesAutoresizingMaskIntoConstraints = NO; 
     innerView.backgroundColor = UIColor.blueColor; 

     [animatingView addSubview:innerView]; 
     innerView.center = animatingView.center; 

     animatingView.center = CGPointMake(self.view.bounds.size.width/2, 
            self.view.bounds.size.height + animatingView.bounds.size.height/2); 
     [self.view addSubview:animatingView]; 
     [UIView animateWithDuration:1 animations:^{ 
      animatingView.center = CGPointMake(self.view.bounds.size.width/2, 
             self.view.bounds.size.height/2); 
     }]; 
    } else { 
     [UIView animateWithDuration:1 animations:^{ 
      animatingView.center = CGPointMake(self.view.bounds.size.width/2, 
             self.view.bounds.size.height + animatingView.bounds.size.height/2); 
     } completion:^(BOOL finished) { 
      [animatingView removeFromSuperview]; 
      animatingView = nil; 
     }]; 
    } 
} 

下面是結果:

enter image description here

+0

當視圖位於屏幕底部時,這不會考慮安全區域。也許我不清楚,但我想要尊重一般安全區插頁。但是,如果我將視圖從屏幕上移動到屏幕上,我不想讓安全區域插圖影響我的內容,除非動畫以視圖重疊安全區域插頁結束。在我的例子中,視圖是從父母邊界開始動畫的,所以不應該應用安全區域插入符號... –