'탬바'에 해당되는 글 2건

  1. 2012.09.04 How to Customize UITabBar on iOS 5
  2. 2012.09.03 Custom Tab Bars
iOS2012. 9. 4. 11:02

How to Customize UITabBar on iOS 5

Building the new version of the app Blocos de Rua I was challenged to customize the UITabBar so it meets what the designer wants. In iOS 5 this is pretty easy to do but I haven’t figured out the proper way to do it from the beginning, this post is my findings on how to do it properly by correctly using the new iOS 5 APIs to customize appearance.

The final look:

Keep reading to see the code.

The appearance APIs in iOS 5 are great. They reduce lots of custom drawRect: that used to be necessary to customize the default UIKit components. The first time I tried to customized the tab bar I had some problems with images been offset upwards because I was using the wrong methods.First thing I learned, the setFinishedSelectedImage:finishedUnselectedImage: from UITabBarItem is the tab’s icon not a image for the whole tab with background, icon and label.

Customize the UITabBar is a peace of cake when you understand how the APIs should be used, take a look:

From inside out, the UITabBar

First - usually in your app delegate - set the image for the entire tab bar’s background, which represents the “normal” state of all tabs. The dimension is 320 x 49 points.

1
[[[self tabBarController] tabBar] setBackgroundImage:[UIImage imageNamed:@"background"]];

Then configure the selected state of a tab. This is necessary because in this app I don’t want the default white highlight that represents the selected tab. Pay attention to the image’s width, it must be the same of a single tab. In my case 320/4, 80 points wide.

1
[[[self tabBarController] tabBar] setSelectionIndicatorImage:[UIImage imageNamed:@"selected"]];

Last but not least, the UITabBarItem

Unlike the default behavior the image shouldn’t change when the tab is selected, this is why I set the same image in both states. For each UIViewController that will be part of the tab bar you need to configure the tab image like this:

1
2
3
4
5
6
7
- (id)init {
    self = [super initWithNibName:@"MyNibName" bundle:nil];
    if (self) {
        self.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"The Title" image:nil tag:0];
        [[self tabBarItem] setFinishedSelectedImage:[UIImage imageNamed:@"tab_icon"] withFinishedUnselectedImage:[UIImage imageNamed:@"tab_icon"]];
    }
}

The last detail is the title’s color on the unselected tab, they can’t be the default gray color. To change the color we need a dictionary of attributes whit the UITextAttributeTextColor key:

1
2
3
4
// below the setFinishedSelectedImage:withFinishedUnselectedImage:
[[self tabBarItem] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor whiteColor], UITextAttributeTextColor,
        nil] forState:UIControlStateNormal];

That’s all folks.

Posted by 다오나무
iOS2012. 9. 3. 13:28

For Gigster’s navigation concept it was necessary to implement a custom styled tab bar. Basically the screen is divided into three parts:

  • Navigation Bar
  • Tab Bar
  • Content

The navigation bar has a custom background image and a fixed title with custom font. The tab bar should be directly under the navigation bar and has complete custom styling.

Basic Setup

To start off I created a new Xcode project and added a UITabBarController with three static views. Although I have XIBs for each content view, I added everything else in code. Each view has a UINavigationController so it can easily contain its own navigation stack.

Navigation Bar

An easy technique to get a custom background in a UINavigationBar is to make a cateogory. Add this code (e.g. in YourAppDelegate.m):

@interface UINavigationBar (MyCustomNavBar)
@end
@implementation UINavigationBar (MyCustomNavBar)
- (void) drawRect:(CGRect)rect 
{
    UIImage *barImage = [UIImage imageNamed:@"nav_bg.png"];
    [barImage drawInRect:rect];    
}
@end

To get the fixed title with custom font I added a method that creates a UILabel:

- (UILabel *)_makeTitleLabel
{
    CGRect frame = CGRectMake(0032044);
    UILabel *label = [[[UILabel alloc] initWithFrame:frame] autorelease];
    label.backgroundColor = [UIColor clearColor];
    label.font = [UIFont fontWithName:@"Marker Felt" size:24];
    label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
    label.textAlignment = UITextAlignmentCenter;
    label.textColor = [UIColor whiteColor];
    label.text = @"Custom Tab Bar";
    
    return label;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    // add static title labels
    [tab1NavigationController.navigationBar addSubview:[self _makeTitleLabel]];
    [tab2NavigationController.navigationBar addSubview:[self _makeTitleLabel]];
    [tab3NavigationController.navigationBar addSubview:[self _makeTitleLabel]];
    ...
}

Tab Bar

A little bit of frame hackery was necessary to get the tab bar right beneath the navigation bar:

    // disable autosizing of tabbar and move it to correct position
    tabBarController.tabBar.autoresizingMask = 0;
    tabBarController.tabBar.frame = CGRectMake(04432065);
    
    
    // fix frame of tabbarcontroller's view
    CGRect frame = tabBarController.view.frame;
    frame.size.height += 29;
    frame.origin.y = 20;
    tabBarController.view.frame = frame;

To have a custom layout for the tab bar, it is necessary to subclass UITabBarController. We don’t need UIKit’s tab bar at all, so we just hide it and create our own custom tabs:

- (void)viewDidLoad
{
    // find the normal tab bar and hide it
    for(UIView *view in self.view.subviews)
    {
        if([view isKindOfClass:[UITabBar class]])
        {
            view.hidden = YES;
            break;
        }
    }
    
    [self _setupCustomTabBar];
}

First I added a UIImageView containing a background image:

- (void)_setupCustomTabBar
{
    // background image
    self.bgImageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tabs_bg.png"]] autorelease];
    bgImageView.frame = CGRectMake(04432065);
    [self.view addSubview:bgImageView];

Next we want to display a tab image to indicate which tab is active:

    self.contentView = [[[UIView alloc] initWithFrame:CGRectMake(04464065)] autorelease];
    [self.view addSubview:self.contentView];
    
    // sliding tab image
    self.tabImage = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tab.png"]] autorelease];
    CGRect frame = self.tabImage.frame;
    frame.origin = CGPointMake(BUTTON_X_OFFSET, BUTTON_Y);
    self.tabImage.frame = frame;
    [self.contentView addSubview:self.tabImage];

Finally I added three buttons to trigger tab selection:

    // Make custom tab buttons and add them to the content view
    [self.contentView addSubview:[self _makeTabButtonWithTitle:@"Tab 1" atIndex:0]];
    [self.contentView addSubview:[self _makeTabButtonWithTitle:@"Tab 2" atIndex:1]];
    [self.contentView addSubview:[self _makeTabButtonWithTitle:@"Tab 3" atIndex:2]];
}

Button creation method:

- (UIButton *)_makeTabButtonWithTitle:(NSString *)title
                              atIndex:(NSInteger)index
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(BUTTON_X_OFFSET + index*BUTTON_WIDTH, BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
    button.tag = index;
    button.titleLabel.font = [UIFont fontWithName:@"Marker Felt" size:18];
    button.titleLabel.shadowColor = [UIColor colorWithWhite:0 alpha:0.5];
    button.titleLabel.shadowOffset = CGSizeMake(0-1);
    [button setTitle:title forState:UIControlStateNormal];
    [button addTarget:self action:@selector(_buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    
    return button;
}

Note that the buttons’ action is _buttonClicked. There we need to set the currently selected tab index in the UITabBarController.

- (void)_buttonClicked:(id)sender
{
    self.selectedIndex = [sender tag];
    [self _updateTabImage];
}

We also want to update the tab image’s position after a tab was selected. This is what _updateTabImage is for:

- (void)_updateTabImage
{
    CGRect targetRect = CGRectMake(BUTTON_X_OFFSET + self.selectedIndex*BUTTON_WIDTH, BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
    
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    
    [self.tabImage setFrame:targetRect];
    
    [UIView commitAnimations];
}

Now we have a fully functioning tab bar with custom layout. You can download the full Xcode project here:MyCustomTabBar_final.zip.

Gigster in the App Store: Jump

Posted by 다오나무