0

I'm trying to show a badge on some UITabBarItems that are configured with an image with UIImageRenderingModeAlwaysOriginal. I'm doing this because the desired effect is something like a raised UITabBarItem a-la Instagram. This is the code I'm using to test this (it's in a UITabBarController category):

- (void) replaceImageForTab:(int)itemIndex
               defaultImage:(UIImage *)defaultImage
              selectedImage:(UIImage *)selectedImage
                      title:(NSString *)title
{
    NSArray *viewControllers = [self viewControllers];
    UIViewController *vc = [viewControllers objectAtIndex:itemIndex];
    [vc.tabBarItem setImage:[defaultImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
    [vc.tabBarItem setSelectedImage:[selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
    [vc.tabBarItem setTitle:title];

    [vc.tabBarItem setBadgeValue:@"1"];
}

However, the badges images are shown clipped, like shown in here:

enter image description here

I think is because the badge is being added within the UITabBar's UIView, and it is clipping its contents. But I can't modify that value since that's a private property. What other options do I have here?

Pierluigi Cifani
  • 224
  • 2
  • 14

1 Answers1

0

I haven't found a way to change the offset in the stock badges, so I had to roll out my own solution. It's not pretty, but it works (this is, again, on a UITabBarController category):

- (void) v_setBadgeValue:(NSString *)badgeValue inTab:(NSInteger)tabIndex
{
    NSArray *viewControllers = [self viewControllers];
    UIViewController *vc = [viewControllers objectAtIndex:tabIndex];
    UITabBarItem *tabBarItem = vc.tabBarItem;

    UIImage *normalImage = tabBarItem.image;
    UIImage *selectedImage = tabBarItem.selectedImage;

    UIImage *badgedNormalImage = [[self class] addBadgeWithValue:badgeValue toImage:normalImage];
    UIImage *badgedSelectedImage = [[self class] addBadgeWithValue:badgeValue toImage:selectedImage];

    [tabBarItem setImage:[badgedNormalImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
    [tabBarItem setSelectedImage:[badgedSelectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];

}

+ (UIImage *) addBadgeWithValue:(NSString *)badgeValue toImage:(UIImage *)image
{
    //Here you have to create your badge view. Let's just use a red square for now
    UIView *badgeView = [[UIView alloc] initWithFrame:CGRectMake(16, 3, 14, 14)];
    [badgeView setBackgroundColor:[UIColor redColor]];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    [imageView addSubview:badgeView];

    UIGraphicsBeginImageContextWithOptions((imageView.bounds.size), NO, [[UIScreen mainScreen] scale]);
    [imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return viewImage;
}

Now you're in complete control of the badges offset and position, that's important if you, like me, have a very strange UITabBar to work with. This is the result:

enter image description here

Pierluigi Cifani
  • 224
  • 2
  • 14