更改 ios 中 UINavigationBar 的背景图像 < 5

发布于 2024-12-28 07:52:50 字数 1989 浏览 1 评论 0 原文

我在更改 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦晓ヶ微光ヅ倾城 2025-01-04 07:52:50

我不想这么说,但是您的方法(添加子视图来保存背景)不会完全按照您提到的原因工作。每次重绘导航栏时,子视图都不会保持其 z 顺序(因此它将覆盖其他 UI 元素)。其他来源描述了此行为(请参阅,例如)

如果您不想使用 swizzling,您可以在类别中重写 drawRect,以便始终正确绘制背景。 (最后一个选项的缺点是应用程序中的任何导航栏都将以相同的背景绘制)。这是我使用的示例代码:

@implementation UINavigationBar (CustomBackground)

 - (void)drawRect:(CGRect)rect { 
    UIImage *image = [UIImage imageNamed: @"back.png"]; 
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
 }
@end

不同的方法可能是:

  1. 子类化 UINavigationBar;
  2. 覆盖drawRect
  3. 在 Interface Builder 中,将导航栏对象的类设置为 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:

@implementation UINavigationBar (CustomBackground)

 - (void)drawRect:(CGRect)rect { 
    UIImage *image = [UIImage imageNamed: @"back.png"]; 
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
 }
@end

A different approach could be:

  1. subclassing UINavigationBar;
  2. overriding drawRect;
  3. in Interface Builder, set the class of your navigation bar object to your UINavigationBar subclass.

I haven't tried it, but it should work.

跨年 2025-01-04 07:52:50

根据要求,这是我的有点顽皮且不太精致的黑客。这实际上只是为了让OP高兴。塞尔吉奥给出了正确的答案。


UINavigationBar+CustomDraw.m

NSString *gNavbarBackgroundImageName = @"default_navbar_background.png";

@implementation UINavigationBar (CustomBackground)

- (void)drawRect:(CGRect)rect 
{ 
    if (gNavbarBackgroundImageName != nil)
    {
        UIImage *image = [UIImage imageNamed:gNavbarBackgroundImageName]; 
        [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    }
}
@end

UINavigationBar+CustomDraw.h

extern NSString *gNavbarBackgroundImageName;

下面是两个视图控制器中的示例用法...


FooViewController.m

#import "UINavigationBar+CustomDraw.h"

@implementation FooViewController

- (void)viewWillAppear:(BOOL)animated
{
    gNavbarBackgroundImageName = @"foo_navbar_background.png";
    [self.navigationController.navigationBar setNeedsDisplay];
}

@end

BarViewController.m

#import "UINavigationBar+CustomDraw.h"

@implementation BarViewController

- (void)viewWillAppear:(BOOL)animated
{
    gNavbarBackgroundImageName = @"bar_navbar_background.png";
    [self.navigationController.navigationBar setNeedsDisplay];
}

@end

现在让我们假设您想要显示一个无样式的导航栏,例如在显示 Facebook 登录页面(由其 SDK 提供)时。

使用它可以防止任何自定义绘图:

gNavbarBackgroundImageName = nil;

注意 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

NSString *gNavbarBackgroundImageName = @"default_navbar_background.png";

@implementation UINavigationBar (CustomBackground)

- (void)drawRect:(CGRect)rect 
{ 
    if (gNavbarBackgroundImageName != nil)
    {
        UIImage *image = [UIImage imageNamed:gNavbarBackgroundImageName]; 
        [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    }
}
@end

UINavigationBar+CustomDraw.h

extern NSString *gNavbarBackgroundImageName;

And here comes the example usage in two view controllers...


FooViewController.m

#import "UINavigationBar+CustomDraw.h"

@implementation FooViewController

- (void)viewWillAppear:(BOOL)animated
{
    gNavbarBackgroundImageName = @"foo_navbar_background.png";
    [self.navigationController.navigationBar setNeedsDisplay];
}

@end

BarViewController.m

#import "UINavigationBar+CustomDraw.h"

@implementation BarViewController

- (void)viewWillAppear:(BOOL)animated
{
    gNavbarBackgroundImageName = @"bar_navbar_background.png";
    [self.navigationController.navigationBar setNeedsDisplay];
}

@end

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:

gNavbarBackgroundImageName = nil;

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文