UINavigationBar 和新的 iOS 5+ 外观 API - 如何提供两个背景图像?

Posted

技术标签:

【中文标题】UINavigationBar 和新的 iOS 5+ 外观 API - 如何提供两个背景图像?【英文标题】:UINavigationBar and new iOS 5+ appearance API - how to supply two background images? 【发布时间】:2011-12-07 08:58:43 【问题描述】:

我想利用新的 ios 5 外观 API 为我的应用程序中的所有 UINavigationBar 实例提供自定义背景图像。要做到这一点,就这么简单:

[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"whatever.png"] forBarMetrics:UIBarMetricsDefault];

但是,对于每个实例,我想根据translucent 属性的值提供不同的图像,例如

// For UINavigationBar instances where translucent returns YES:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"whatever-translucent.png"] forBarMetrics:UIBarMetricsDefault];

// Otherwise:

[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"whatever.png"] forBarMetrics:UIBarMetricsDefault];

鉴于外观 API 似乎是使用类方法配置的,这样的事情可能吗?

【问题讨论】:

【参考方案1】:

目前,无法执行您所描述的操作 - 外观代理在您调用它时对任何特定实例一无所知。

实际上,您可能需要做的是弄清楚您有多少半透明条与您有多少非半透明条。选择您拥有的更多并为其使用外观代理 - 对于其他人,当您将其设置为半透明(或要求全屏布局)时,您必须设置背景图像。

与此同时,您能否就您的要求向http://bugreport.apple.com/ 提交增强请求?这不是一个不合理的要求。谢谢!

【讨论】:

是的,这就是我在过去几分钟内想出的内容......谢谢。【参考方案2】:

您可以使用类外观代理对其进行全局设置,也可以将其设置在导航栏的实例上。

我目前正在为导航栏的一个实例设置背景,它似乎正在工作。我有两个不同背景的不同导航栏。如果你在一个实例上设置它,你应该能够调节代码。

UINavigationController *myNavController = [[UINavigationController alloc] initWithRootViewController:myView];
[viewControllers addObject:myNavController];

// not supported on iOS4
UINavigationBar *navBar = [myNavController navigationBar];
if ([navBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)])

    // right here, you could condition bg image based on properties of this instance
    // of the navBar or any other condition.

    [navBar setBackgroundImage:[UIImage imageNamed:@"bg.jpg"] forBarMetrics:UIBarMetricsDefault];

如果要使用类方法设置,可以为所有设置:

[[UINavigationBar appearance] setBackground ...

我承认它很新,我只是像大多数人一样弄清楚它。

【讨论】:

我试图在全局范围内实现这一点,对于任何 UINavigationBar 实例,所以实例方法不会削减它 - 本质上,我想使用类方法,但让它设置不同的图像当外观代理将自身应用于每个实例时,基于半透明属性的值......我想我可能不走运...... 我不知道除了在实例级别上执行此操作之外的其他方法 - 这确实会让您乱扔代码但您可以有一个通用的方法来做到这一点。 我在看的另一件事是外观WhenContainedIn,但我认为这也对您没有帮助,因为这更多的是关于控制使用哪种外观的视图类型... 您可能会考虑 UINavigationBar、UINavigationBarTranslucent 或其他的子类,并使用 appearanceWhenContainedIn 类方法。仍然很痛苦,但是您不必为特定实例“乱扔”代码。【参考方案3】:

这个答案可能对您没有太大帮助,但对其他人可能有用。如果您创建一个子类,您可以分别指定每个子类的外观。例如,我有 UITableviewCells 和一个从 UITableViewCells 派生的自定义类。实际上我这样做是有原因的,但我发现我需要专门为这两个类调用 [[UITableViewCells appearance] setFont:[...]] 。

由于您似乎希望基于一个直到运行时才知道的变量来执行此操作,所以您可能不走运!

【讨论】:

【参考方案4】:

如果你知道哪些类包含半透明条,你可以这样做:

[[UIBarButtonItem appearanceWhenContainedIn:[MyClassWithTranslucentBar class], [MyOtherClassWithTranslucentBar class], nil]
    setTintColor:desiredColor];

【讨论】:

【参考方案5】:

我不能发表评论,所以必须回答。 Rob Whitlow 就此写了一篇很棒的文章。看看吧:http://ios-blog.co.uk/tutorials/ios-custom-ui-series-tabbar-navbar/

【讨论】:

【参考方案6】:

试试这个:

if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) 


        // Load resources for iOS 6.1 or earlier

         navigationController1 = [self customizedNavigationController];
         [navigationController1 setViewControllers:[NSArray arrayWithObject: self.homeViewController]];

         [self setNavigationController:navigationController1];
         [self.window setRootViewController:navigationController];


     else 
        // Load resources for iOS 7 or later
         navigationController1 = [[UINavigationController alloc] initWithRootViewController:self.homeViewController];
          [self.window setRootViewController:navigationController1];
    


  - (UINavigationController *)customizedNavigationController 

     UINavigationController *navController = [[UINavigationController alloc]   initWithNibName:nil bundle:nil];

    // Ensure the UINavigationBar is created so that it can be archived. If we do not access the
    // navigation bar then it will not be allocated, and thus, it will not be archived by the
    // NSKeyedArchvier.
    [navController navigationBar];

    // Archive the navigation controller.
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:navController forKey:@"root"];
    [archiver finishEncoding];

    // Unarchive the navigation controller and ensure that our UINavigationBar subclass is used.
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    [unarchiver setClass:[LNTNavigationBar class] forClassName:@"UINavigationBar"];
    UINavigationController *customizedNavController = [unarchiver decodeObjectForKey:@"root"];
    [unarchiver finishDecoding];

    // Modify the navigation bar to have a background image.
    LNTNavigationBar *navBar = (LNTNavigationBar *)[customizedNavController navigationBar];
    [navBar setTintColor:[UIColor colorWithRed:0.39 green:0.72 blue:0.62 alpha:1.0]];
    [navBar setBackgroundImage:[UIImage imageNamed:@"nav_bar_1024_46.png"] forBarMetrics:UIBarMetricsDefault];
    [navBar setBackgroundImage:[UIImage imageNamed:@"nav_bar_1024_46.png"] forBarMetrics:UIBarMetricsLandscapePhone];

    return customizedNavController;

【讨论】:

以上是关于UINavigationBar 和新的 iOS 5+ 外观 API - 如何提供两个背景图像?的主要内容,如果未能解决你的问题,请参考以下文章

新的ios5api:自定义UINavigationBar背景属性与简单的功能!!!

iOS 应用程序在更新到新版本和新的 firebasedb 后崩溃

iOS 5 - 1 自定义 UINavigationBar 不同于所有其他

UINavigationBar 自定义背景与悬垂(iOS 5)

为所有导航栏 (UINavigationBar) iOS 5.1+ 设置按钮和外观

嵌入 UISplitViewController 时,UINavigationBar 中缺少 iOS11 UISearchBar