導航欄在實際應用中會有很多,跟隨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 中也進行相應的代碼,只是改變的效果不同罷了。
是不是很簡單。效果非常的完美,在iPhone 10上面,也表現的很棒,看下效果圖
QQ20170920-175814.gif
QQ20170920-175707.gif