2017-10-10 33 views
4

次のことを考慮してください:バックグラウンドを持ち、サブビューにレイアウトされたいくつかのコンテンツを持つ再利用可能なUIViewサブクラスを作成しました。それは自動的に(iPhone X上など)、必要なときにその内容をはめ込みますように、私は責任を開発者として、私は、その安全な領域に基づいて、ビューのサブビューを揃えました:iOS 11安全領域対UIViewアニメーション

center vs bottom

素晴らしいです!内側の図は、安全な領域の内側にあるときに端から端に向かって行き、安全な領域から外に出るときにその内容を底からはめ込みます。

最初にビューをオフスクリーンにする必要があるとしましょうが、ユーザーがアプリのどこかをタップすると、ビューが画面中央にアニメーション表示され、2番目のタップでアニメーション化されます。さんはこのようにそれを実装してみましょう:

だから、
@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

これは私のために、まだ受け入れられません。すべての面で5フィートの詰め物が入っているように、スライドさせたようにスライドさせたい。

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

ビューが画面の下部に配置されている場合、これはセーフエリアを尊重しません。たぶん私ははっきりしていなかったかもしれませんが、私は一般的に安全な場所のインセットを尊重したいと思います。しかし、私が画面からアニメーション化している場合、アニメーションがセーフエリアのインセットと重なるビューで終了しない限り、セーフエリアのインセットが私のコンテンツに影響を及ぼさないようにします。私の例では、ビューは親の境界からアニメーション化されているため、安全な領域のインセットは適用しないでください... –

関連する問題