简体   繁体   中英

How do I get the width of a UITabBarItem?

The width of a UITabBarItem varies, depending on how many there are.

How do I determine how wide my tab bar items are?

I'm looking for a property if possible, as opposed to a mathematical formula, since on the iPad, there is also an issue of padding on either side of the tab bar. Consider these screenshots. Notice the padding on either side of the tab bar items on the iPad (highlighted with the red boxes). This padding does not exist on the iPhone.

The iPad:

在此输入图像描述

The iPhone: 在此输入图像描述

Edit : It has been noted in the comments below that this solution did not work in a beta version of iOS 5, so be prepared to modify it to meet your needs.

I think in order to do this the right way, you have to be able to get to the frame of each tab bar item. Fortunately, this is possible:

CGFloat tabBarTop = [[[self tabBarController] tabBar] frame].origin.y;
NSInteger index = [[self tabBarController] selectedIndex];
CGFloat tabMiddle = CGRectGetMidX([[[[[self tabBarController] tabBar] subviews] objectAtIndex:index] frame]);

The above code gives you the y coordinate of the top of the tab bar and the x coordinate of the middle of the selected tab item. From here, you can add your indicator view to the tab bar controller's view relative to this point.

Disclaimer : The danger with this approach is that it peeks under the hood of the UITabBar class by accessing its view hierarchy and the frame property of instances of the private UITabBarButton class. It is possible (however unlikely) that this approach could be affected/broken by a future iOS update. However, you're not accessing any private APIs, so this shouldn't get your app rejected from the App Store.

I made a simple iPad project demonstrating how it works , complete with animations.

Swift 3

I created a shared instance in UIApplication then pulled my subviews width

tabBarController?.tabBar.subviews[1].frame.width

I tried these 2 properties of UITabBar:

@property(nonatomic) CGFloat itemWidth NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
@property(nonatomic) CGFloat itemSpacing NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;

But get zero value as Vive said. So I wrote some codes to get the right width:

    CGFloat tabBarItemWidth = 0;
    for (UIView *view in [self.tabBarController.tabBar subviews]) {
        if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            if (tabBarItemWidth == 0) {
                tabBarItemWidth = view.frame.origin.x;
            } else {
                tabBarItemWidth = view.frame.origin.x - tabBarItemWidth;
                break;
            }
        }
    }

Why not use the width of first UITabBarButton? Because there are spaces between tab bar buttons. :)

Looking at the answer above:

  1. Items in the UITabBar work different in the iPhone and the iPad. In the iPhone they fill whole width, in the iPad they're centered horizontally.
  2. There is a spacing between the items in the iPad.
  3. You can set the values for both width and spacing using tabBar.itemWidth or tabBar.itemSpacing . You are not able to read system spacing or width from it - you'll receive 0 unless you set it.

So here's my sample how to get frames of all UITabBarItems :

// get all UITabBarButton views
    NSMutableArray *tabViews = [NSMutableArray new];
    for (UIView *view in self.tabBar.subviews) {
        if ([view isKindOfClass:[UIControl class]]) {
            [tabViews addObject:[NSValue valueWithCGRect:view.frame]];
        }
    }

    // sort them from left to right
    NSArray *sortedArray = [tabViews sortedArrayUsingComparator:^NSComparisonResult(NSValue *firstValue, NSValue *secondValue) {
        CGRect firstRect = [firstValue CGRectValue];
        CGRect secondRect = [secondValue CGRectValue];

        return CGRectGetMinX(firstRect) > CGRectGetMinX(secondRect);
    }];

Now you have a table of frames, corresponding to your tabbar items. You can eg. place an imageView on selected index button frame.

    CGRect frame = self.tabBar.bounds;
    CGSize imageSize = CGSizeMake(CGRectGetWidth(frame) / self.tabBar.items.count, self.imageView.image.size.height);
    CGRect selectedRect = sortedArray.count > self.selectedIndex ? [sortedArray[self.selectedIndex] CGRectValue] : CGRectZero;
    [self.imageView setFrame:CGRectIntegral(CGRectMake(CGRectGetMinX(selectedRect), CGRectGetMaxY(frame) - imageSize.height,
                                                       CGRectGetWidth(selectedRect), imageSize.height))];

You can get tabBarItem view using private property view . Then just get view frame .

- (CGRect)rectForTabBarItem:(UITabBarItem *)tabBarItem {
    UIView *itemView = [tabBarItem valueForKey:@"view"];
    return itemView.frame;
} 

UITabBarItem inherits from UIBarItem, which inherits from NSObject. Since it doesn't inherit from UIView, I don't know that you're going to be able to get the information you want just with a property. I know you don't want a mathematical way of doing it, but it would seem that getting the frame of the tab bar and dividing by the # of tabs would be a reasonable option that should work regardless of the hardware (iphone vs ipad). Padding shouldn't affect this, right? So you'd have:

tabSize = tabbar.frame.size.width / [tabbar.items count];
tabBarStart = tabbar.frame.origin.x;

// Assume index of tabs starts at 0, then the tab in your pic would be tab 4
//   targetX would be the center point of the target tab.
targetX = tabBarStart + (tabSize * targetTabIndex) + (tabSize / 2);

I, as well, am interested to know if someone finds a simple property to give this information.

Loop through your tabBar's subviews and find the views with the class "UITabBarButton". These are the views for each tab item.

for (UIView *view in self.tabBar.subviews) {
    if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
        // view.frame contains the frame for each item's view
        // view.center contains the center of each item's view
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM