导航栏在实际应用中会有很多,跟随scrollview改变其透明度或偏移的效果。以往是使用hide导航后,再使用自定的方式实现。但仔细观察一些大的APP可以发现,顶部的items或背景都是有转场效果的。所以,一直在考虑如何实现,同时可以兼容iPhone X。
方案
1、跟随滚动时,导航栏偏移,这个可以直接通过改变导航栏frame的方式改变
2、透明度变化,最开始我的方案是通过原生方法,不断根据透明度的值去生成新的图片或背景色来修改,效果是可以实现的。但是在两个controller之前转场时,就会显的非常木
3、最后还是使用了自定义背景view的方案来解决的,经测试在iphoneX上面也是完美的。
创建一个UINavigationBar的category,直接上代码
static char customBackgroundImageViewKey;
/**
使用此方法,通过以下设置原生的背景图及shadow为透明
[xxx setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[xxx setShadowImage:[UIImage new]];
*/
@implementation UINavigationBar (LGXBackground)
- (UIImageView *)customBackgroundImageView
{
return objc_getAssociatedObject(self, &customBackgroundImageViewKey);
}
- (void)setCustomBackgroundImageView:(UIImageView *)customBackgroundImageView
{
objc_setAssociatedObject(self, &customBackgroundImageViewKey, customBackgroundImageView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#pragma mark - 设置项
/// 设置背景色
- (void)lgx_setBackgroundColor:(UIColor *)backgroundColor
{
[self checkOverlayView];
[self.customBackgroundImageView setBackgroundColor:backgroundColor];
}
/// 设置背景图
- (void)lgx_setBackgroundImage:(UIImage *)image
{
[self checkOverlayView];
[self.customBackgroundImageView setImage:image];
}
/// 设置背景alpha
- (void)lgx_setBackgroundAlpha:(float)alpha
{
[self checkOverlayView];
self.customBackgroundImageView.alpha = alpha;
}
/// 设置shadow
- (void)lgx_setShadowImage:(UIImage *)image
{
}
- (void)checkOverlayView
{
if (!self.customBackgroundImageView) {
UIView *contentView = self.subviews.firstObject;
CGFloat width = CGRectGetWidth(self.bounds);
CGFloat height = CGRectGetHeight(self.bounds) + [UIApplication sharedApplication].statusBarFrame.size.height;
self.customBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, contentView.bounds.size.height - height, width, height)];
self.customBackgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
[contentView insertSubview:self.customBackgroundImageView atIndex:0];
}
}
@end
4、至此就可以通过scrollView的变化来修改两个属性变化了,下面我们来说一下转场动画
转场
其实转场有很多种,我觉得这篇文章讲的很好。有兴趣的可以仔细阅读一下。但是我使用了另一个API
UIViewController的 transitionCoordinator属性
这个属性向我们提供一个非常简单的API,但是却可以帮助我们实现一些转场效果,下面贴下代码。
// from controller
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
// change alpha or frame ...
} completion:NULL];
}
// 同样在 target controller 中也进行相应的代码,只是改变的效果不同罢了。
QQ20170920-175814.gif QQ20170920-175707.gif是不是很简单。效果非常的完美,在iPhone 10上面,也表现的很棒,看下效果图
网友评论