我在更改 IOS 版本 UINavigationBar
的背景图像时遇到问题 UINavigationBar
5. 我已经读到了一个很好的解决方案,该解决方案基于方法调配,但该解决方案的问题是,当我添加图像时,它涵盖了包括导航栏上的按钮在内的所有内容。
我找到了一个对我部分有用的解决方案,它基于以下代码:
@interface UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag;
-(void)resetBackground:(NSInteger)bgTag;
@end
@implementation UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag{
if(image == NULL){ //might be called with NULL argument
return;
}
UIImageView *aTabBarBackground = [[UIImageView alloc]initWithImage:image];
aTabBarBackground.frame = CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
aTabBarBackground.tag = bgTag;
[self addSubview:aTabBarBackground];
//[self sendSubviewToBack:aTabBarBackground];
[aTabBarBackground release];
}
-(void)setRightButton:(UIButton*)button withTag:(NSInteger)bgTag{
if(button == NULL){ //might be called with NULL argument
return;
}
[self addSubview:button];
}
/* input: The tag you chose to identify the view */
-(void)resetBackground:(NSInteger)bgTag {
[self sendSubviewToBack:[self viewWithTag:bgTag]];
}
@end
我在我的 ViewWillAppear
方法中使用了这个类别,如下所示:
-(void) viewWillAppear:(BOOL)animated {
UIImage *backgroundImage = [UIImage imageNamed:@"background_confernce_import_logo"];
if ([self.navigationController.navigationBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)])
{
[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
}
else{
[[self.navigationController navigationBar] setBackgroundImage:backgroundImage withTag:8675309];
}
}
在 else 子句中,我调用 setBackgroundImage
。没关系,但问题是,如果我在第 1 页的导航栏上有一个右键,然后返回第 1 页后转到第 2 页,该按钮就会消失。我应该在应用程序的每个页面中更改导航栏的背景图像,就像在放置新图像的 viewWillAppear
方法中一样。
任何帮助将不胜感激。在IOS 5下不存在这样的问题,但它应该在两个版本上都可以工作。
I have a problem to change the background image of a UINavigationBar
for IOS version < 5. I read already about one good solution, which is based on method swizzling, but the problem of this solution is when I add the image it covers everything include the buttons on a navigation bar.
I found a solution which partially worked for me it is base on a following code:
@interface UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag;
-(void)resetBackground:(NSInteger)bgTag;
@end
@implementation UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag{
if(image == NULL){ //might be called with NULL argument
return;
}
UIImageView *aTabBarBackground = [[UIImageView alloc]initWithImage:image];
aTabBarBackground.frame = CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
aTabBarBackground.tag = bgTag;
[self addSubview:aTabBarBackground];
//[self sendSubviewToBack:aTabBarBackground];
[aTabBarBackground release];
}
-(void)setRightButton:(UIButton*)button withTag:(NSInteger)bgTag{
if(button == NULL){ //might be called with NULL argument
return;
}
[self addSubview:button];
}
/* input: The tag you chose to identify the view */
-(void)resetBackground:(NSInteger)bgTag {
[self sendSubviewToBack:[self viewWithTag:bgTag]];
}
@end
I used this Category in my ViewWillAppear
methods like this:
-(void) viewWillAppear:(BOOL)animated {
UIImage *backgroundImage = [UIImage imageNamed:@"background_confernce_import_logo"];
if ([self.navigationController.navigationBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)])
{
[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
}
else{
[[self.navigationController navigationBar] setBackgroundImage:backgroundImage withTag:8675309];
}
}
In else clause I call setBackgroundImage
. It is ok, but the problem is that if I have a right button on navigation bar of page 1 for example and go to page 2 after come back to page 1 the button is disappear. I should change the background image of navigation bar in every page in my application like this in viewWillAppear
method where I put the new image.
Any help will be appreciated. Under IOS 5 there are no such problem, but it should work on both versions.
发布评论
评论(2)
我不想这么说,但是您的方法(添加子视图来保存背景)不会完全按照您提到的原因工作。每次重绘导航栏时,子视图都不会保持其 z 顺序(因此它将覆盖其他 UI 元素)。其他来源描述了此行为(请参阅此,例如)
如果您不想使用 swizzling,您可以在类别中重写
drawRect
,以便始终正确绘制背景。 (最后一个选项的缺点是应用程序中的任何导航栏都将以相同的背景绘制)。这是我使用的示例代码:不同的方法可能是:
UINavigationBar
;drawRect
;UINavigationBar
子类。我还没有尝试过,但它应该有效。
I hate to say it, but your approach (adding a subview to hold the background) will not work exactly for the reason you mention. Each time the navigation bar is redrawn, the subview will not keep its z-order (and thus it will cover other UI elements). This behavior is described by other sources (see this, e.g.)
If you don't want to use swizzling, you could override
drawRect
in a category, so that the background is always drawn correctly. (this last option has the drawback that any navigation bar in your app will be drawn with the same background). This is a sample code I use:A different approach could be:
UINavigationBar
;drawRect
;UINavigationBar
subclass.I haven't tried it, but it should work.
根据要求,这是我的有点顽皮且不太精致的黑客。这实际上只是为了让OP高兴。塞尔吉奥给出了正确的答案。
UINavigationBar+CustomDraw.m
UINavigationBar+CustomDraw.h
下面是两个视图控制器中的示例用法...
FooViewController.m
BarViewController.m
现在让我们假设您想要显示一个无样式的导航栏,例如在显示 Facebook 登录页面(由其 SDK 提供)时。
使用它可以防止任何自定义绘图:
注意 Apple 的某些组件在您可能没有想到的地方使用 UINavigationBar。例如,
MPMoviePlayerController
使用自定义导航栏来显示其 UI 的上半部分 - 因此这将是您想要阻止自定义绘制的另一种情况。As per request, here comes my slightly naughty and not really polished hack. This is really just for making the OP happy. The right answer was given by sergio.
UINavigationBar+CustomDraw.m
UINavigationBar+CustomDraw.h
And here comes the example usage in two view controllers...
FooViewController.m
BarViewController.m
Now let us assume you want to show a non-styled navigation bar, for example when displaying a Facebook login page (as provided by their SDK).
Use this to prevent any custom drawing:
Note Some of Apple's components use the UINavigationBar at places you might not have thought of. For example, the
MPMoviePlayerController
uses a custom navigation bar for displaying the upper part of its UI - so that would be another case where you want to prevent custom drawing.