我找到了一个可行的解决方案,尽管它确实有点像 hack。
这个想法是给半透明的导航栏一个不透明的支持。不幸的是,我对解决方案不满意,因为它很脏,没有封装并引入了一些潜在的问题,但我很高兴,因为它完成了工作。
在我的应用程序的基本视图控制器类(即 MyViewController : UIViewController)中,在 viewDidLoad 方法中,我实例化了一个新的 ivar UIView *_navigationBarBG 并赋予它与 self.navigationController.navigationBar 相同的框架。然后我将它的 backgroundColor 属性设置为 [UIColor whiteColor] 虽然我猜这是你实现更多色调的方式。[编辑:如果您想成为一个纯粹主义者(颜色值与来自 .psd 的颜色值完全相同),您可以将 _navigationBarBG 设为 UIImageView 并在那里使用您的自定义背景,以及您设置的实际 UINavigationBar 的背景以清晰显示(如果您想使用互联网上某处典型的“使用图像更改导航栏”配方,或者拉伸 1px 透明图像)]
if(self.navigationController)
{
_navigationBarBG = [[UIView alloc] initWithFrame: self.navigationController.navigationBar.frame];
_navigationBarBG.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_navigationBarBG];
}
然后,(这是蹩脚的部分,但我没有看到任何其他方式),我将此视图添加为子视图。但是,每当您通常调用 [self.view addSubview: anyView] 时,您必须确保调用 [self.view insertSubview: anyView belowSubview: _navigationBarBG];
if (_navigationBarBG)
[self.view insertSubview: anyView belowSubview:_navigationBarBG];
else
[self.view addSubview: anyView];
如果您忘记了这一点,这些添加的视图将在您的导航栏背景下滑动并且看起来很奇怪。所以你需要知道这是错误的来源。
我为什么要这样做?您可能会再次问... 这是通过使用 scrollView 委托 (scrollViewDidScroll:) 和 viewWillAppear 来完成的:
// FIRST DEAL WITH SCROLLING NAVIGATION BAR
CALayer *layer = self.navigationController.navigationBar.layer;
CGFloat contentOffsetY = scrollView.contentOffset.y;
CGPoint newPosition;
if (contentOffsetY > _scrollViewContentOffsetYThreshold && self.scrollingNavigationBarEnabled) {
newPosition = CGPointMake(layer.position.x,
22 - MIN((contentOffsetY - _scrollViewContentOffsetYThreshold), 48.0)); // my nav bar BG image is 48.0 tall
layer.position = newPosition;
[_navigationBarBG setCenter: newPosition]; // if it's nil, nothing happens
}
else
{
newPosition = kNavBarDefaultPosition; // i.e. CGPointMake(160, 22) -- portrait only
layer.position = newPosition;
[_navigationBarBG setCenter: newPosition]; // if it's nil, nothing happens
}