iOS 11安全区域与UIView动画

Tam*_*ola 7 uikit ios autolayout ios11 iphone-x

请考虑以下内容:我创建了一个可重用的UIView子类,它具有一个背景,并在其子视图中列出了一些内容.作为负责任的开发人员,我根据其安全区域对齐了视图的子视图,以便在必要时自动插入其内容(例如在iPhone X上):

中心vs底部

优秀!当内部视图位于安全区域内时,内部视图是边对边的,当它从安全区域悬挂出来时,内部视图将其内容从底部插入.

现在让我们说最初视图应该在屏幕外,但是当用户点击我的应用程序中的某个地方时,我希望我的视图动画到屏幕的中心,它应该在第二次点击时动画显示.让我们像这样实现它:

@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
Run Code Online (Sandbox Code Playgroud)

所以,现在如果我们启动应用程序并点击屏幕,就会发生这种情况:

动画片

到现在为止还挺好.但是,当我们再次点击它时会发生这种情况:

动画出来

正如您所看到的,即使视图完全超出了超视图的范围,安全区域插入仍然会被设置为好像它位于超视图的底部.

我们可以通过调用[self.view layoutIfNeeded]视图动画的动画块来使效果不那么突然,但它并没有消除问题 - 底部空间将以动画方式增长而不是突然扩展:

更好,但仍然很糟糕

这对我来说仍然是不可接受的.我希望它滑出来,就像它滑入一样,所有侧面都有5pt填充.

有没有办法实现这一点,而不添加喜欢shouldAlignContentToSafeAreashouldAlignContentToBounds我的视图标志?

我只是想让它自动工作,但工作正常 ......

Kru*_*nal 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;
        }];
    }
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

在此输入图像描述