iOS开发仿美国国家地理App的一个炫酷的动画

WzxJiang

编辑:Bison
投稿:WzxJiang

"这个是模仿美国国家地理App的一个View弹出动画,看上去很简单但却有很多细节,废话不多说,直接讲解。"


前几天,产品那边给了这样一个需求给我:

1

这个是模仿美国国家地理App的一个View弹出动画,看上去很简单但却有很多细节,废话不多说,直接讲解。

###把这个gif分解可以看出这个View弹出的时候有这几步:

状态栏隐藏

弹出View

能拖动View,往上拖到一定位置导航栏显示正好和View切合,往下拖有回弹效果

屏幕左上角有个返回按钮,且能随着导航栏显示变色

####让我们一步步来解决

1.状态栏隐藏

可以通过下面这个方法来解决

- (BOOL)prefersStatusBarHidden
{
    return YES;//隐藏为YES,显示为NO
}

2.弹出View

这个不难直接贴代码了

//如果_popView不存在 创建
if (!_popView)
{
    _popView = ({
        UIView * popView = [[UIView alloc]initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height)];

        popView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];

        popView.userInteractionEnabled = YES;

        popView;
    });

    _popSubView = ({
        UIView * popSubView = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height, self.view.frame.size.width, self.view.frame.size.height)];

        [popSubView addGestureRecognizer:[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)]];

        popSubView.backgroundColor = [UIColor whiteColor];

        popSubView;
    });
        [_popView addSubview:_popSubView];
    }

    [self.view addSubview:_popView];

    [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{

        CGRect rect    = _popSubView.frame;
        rect.origin.y  = self.view.frame.size.height/3.0;
        _popSubView.frame = rect;

    } completion:^(BOOL finished) {

    }];
}

3.能拖动View,往上拖到一定位置导航栏显示正好和View切合,往下拖有回弹效果
上面我们已经添加了拖动手势

[popSubView addGestureRecognizer:[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)]];


先贴这个方法中的全部代码,看代码的注释应该就能看懂了

- (void)pan:(UIPanGestureRecognizer *)sender
{
    //手指在self.view上的偏移量
    CGPoint trans = [sender translationInView:sender.view];

    CGPoint oldCenter = sender.view.center;

    oldCenter.y += trans.y;

    //设置view最高点  self.navigationController.navigationBar.frame.size.height使得View能完美切合
    if (oldCenter.y <= self.view.center.y + self.navigationController.navigationBar.frame.size.height)
    {
        oldCenter.y = self.view.center.y + self.navigationController.navigationBar.frame.size.height;
        //使导航栏以动画效果显示
        [self.navigationController setNavigationBarHidden:NO animated:YES];
        [_backBtn setBackgroundImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
    }
    else
    {
        [self.navigationController setNavigationBarHidden:YES animated:YES];
        [_backBtn setBackgroundImage:[UIImage imageNamed:@"back(white)"] forState:UIControlStateNormal];
    }

    //设置view最低点 +50是为了回弹效果
    if(oldCenter.y  > self.view.center.y + self.view.frame.size.height/3.0 + 50)
    {
        oldCenter.y = self.view.center.y + self.view.frame.size.height/3.0 + 50;
    }

    //回弹效果
    if (sender.state == UIGestureRecognizerStateEnded)
    {
        if(oldCenter.y  >= self.view.center.y + self.view.frame.size.height/3.0)
        {
            oldCenter.y = self.view.center.y + self.view.frame.size.height/3.0;
        }

        [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            sender.view.center = oldCenter;
        } completion:^(BOOL finished) {

        }];
    }
    else
    {
        sender.view.center = oldCenter;
    }
    [sender setTranslation:CGPointZero inView:sender.view];
}


4.屏幕左上角有个返回按钮,且能随着导航栏显示变色

能不被导航栏覆盖说明肯定要加在window上,而且要变色的话有两种方式:

画CAlayer,这样的颜色变化动画会更逼真

我这里用的是第二种方法,直接用两种颜色的icon,变btn的背景图片就行了

if (!_backBtn)
{
    _backBtn = ({

        UIButton * backBtn = [UIButton buttonWithType:UIButtonTypeCustom];

        backBtn.frame = CGRectMake(10, 10, 13, self.navigationController.navigationBar.frame.size.height - 20);

        [backBtn addTarget:self action:@selector(hidePopView) forControlEvents:UIControlEventTouchUpInside];

        [backBtn setBackgroundImage:[UIImage imageNamed:@"back(white)"] forState:UIControlStateNormal];

        backBtn;
    });
}
[[UIApplication sharedApplication].windows[0] addSubview:_backBtn];

隐藏就很简单了

- (void)hidePopView
{
    [UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{

        CGRect rect    = _popSubView.frame;
        rect.origin.y  = self.view.frame.size.height;
        _popSubView.frame = rect;
        if (self.navigationController.navigationBarHidden == NO)
        {
        [self.navigationController setNavigationBarHidden:YES animated:YES];
        }
        [_backBtn removeFromSuperview];

    } completion:^(BOOL finished) {

        [self changeBarStatus];
        [_popView removeFromSuperview];

    }];
}


btn的点击方法就直接用这个了

[backBtn addTarget:self action:@selector(hidePopView) forControlEvents:UIControlEventTouchUpInside];

完整代码
GitHub:Wzxhaha


博主app上线啦,快点此来围观吧

更多经验请点击

好文推荐:Bison眼中的iOS开发多线程是这样的(一)


分享文章