【问题标题】:How do I get the width of a UITabBarItem?如何获得 UITabBarItem 的宽度?
【发布时间】:2011-07-29 05:49:06
【问题描述】:

UITabBarItem 的宽度会有所不同,具体取决于有多少。

如何确定标签栏项目的宽度?

如果可能的话,我正在寻找属性,而不是数学公式,因为在 iPad 上,标签栏两侧也存在填充问题。考虑这些屏幕截图。注意 iPad 上标签栏项目两侧的填充(用红色框突出显示)。 iPhone 上不存在此填充。

iPad:

iPhone:

【问题讨论】:

  • 你想达到什么目标?
  • 我想在标签栏上方居中放置一个箭头,就像 twitter 应用一样。
  • 我想补充一点,我有箭头在 iPhone 上工作。我只是不确定如何处理 iPad 上的填充。
  • @NickWeaver - 请看截图。我想让图像居中在选定的选项卡上。
  • 我明天再研究一下,需要睡觉 :)

标签: iphone ios uitabbar uitabbaritem


【解决方案1】:

UITabBarItem 继承自 UIBarItem,UIBarItem 继承自 NSObject。由于它不是从 UIView 继承的,因此我不知道您是否能够仅通过属性获得所需的信息。我知道您不想要一种数学方法,但似乎获取标签栏的框架并除以标签的数量将是一个合理的选择,无论硬件如何(iphone vs ipad)都应该有效.填充不应该影响这一点,对吧?所以你有:

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);

我也很想知道是否有人找到了一个简单的属性来提供此信息。

【讨论】:

  • 问题是,您将无法使用灵活空间。
  • @Moshe,这些照片很有帮助。我更新了我的答案以说明填充。我知道这不是您想要的(即为您提供的财产),抱歉。不过,希望这会有所帮助。
  • 不起作用,标签栏的原点在屏幕左侧的 0 处。 Apple 使用某种内部视图来使选项卡居中。
【解决方案2】:

编辑:已在下面的 cmets 中指出,此解决方案在 iOS 5 的 beta 版本中不起作用,因此请准备好对其进行修改以满足您的需求。

我认为为了以正确的方式执行此操作,您必须能够到达每个标签栏项目的框架。幸运的是,这是可能的:

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

上面的代码给出了标签栏顶部的 y 坐标和所选标签项中间的 x 坐标。从这里,你可以将你的指示器视图添加到标签栏控制器相对于这一点的视图中。

免责声明:这种方法的危险在于它通过访问其视图层次结构和私有 UITabBarButton 类实例的 frame 属性来窥视 UITabBar 类的底层.这种方法有可能(但不太可能)会受到未来 iOS 更新的影响/破坏。但是,您没有访问任何私有 API,因此这不会导致您的应用被 App Store 拒绝。

我制作了a simple iPad project demonstrating how it works,并附有动画。

【讨论】:

  • 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. 我不知道这是可能的。我不确定这是否会获得批准。此外,似乎有比标签栏项目更多的子视图。
  • @Moshe:我认为这不是问题,因为您没有调用任何私有方法,而且我认为没有更好的方法来完成您想做的事情。有谁知道苹果是否允许这种代码?
  • 我在一个应用程序中使用它。如果它得到苹果,你也有我的支持。
【解决方案3】:

遍历您的 tabBar 的子视图并找到具有“UITabBarButton”类的视图。这些是每个选项卡项的视图。

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
    }
}

【讨论】:

  • 这个访问私有API,什么会导致应用被苹果拒绝,所以很遗憾-1。
【解决方案4】:

我尝试了UITabBar的这2个属性:

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

但正如 Vive 所说,获得零价值。所以我写了一些代码来获得正确的宽度:

    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;
            }
        }
    }

为什么不使用第一个 UITabBarButton 的宽度?因为标签栏按钮之间有空格。 :)

【讨论】:

  • 这是自定义尺寸 - 除非你设置它,否则它是 0。
  • 是的,我通过这 2 个属性(UITabBar.itemWidth 和 UITabBar.itemSpacing)得到了零值。我已经更新了答案。感谢万岁。
【解决方案5】:

看上面的答案:

  1. UITabBar 中的项目在 iPhone 和 iPad 中的工作方式不同。在 iPhone 中,它们填充整个宽度,在 iPad 中,它们水平居中。
  2. iPad 中的项目之间存在间距。
  3. 您可以使用tabBar.itemWidthtabBar.itemSpacing 设置宽度和间距的值。您无法从中读取系统间距或宽度 - 除非您设置它,否则您将收到 0

这是我的示例,如何获取所有 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);
    }];

现在您有一个框架表,对应于您的标签栏项目。你可以例如。在选定的索引按钮框架上放置一个 imageView。

    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))];

【讨论】:

    【解决方案6】:

    您可以使用私有属性view 获取 tabBarItem 视图。然后查看frame

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

    【讨论】:

      【解决方案7】:

      斯威夫特 3

      我在 UIApplication 中创建了一个共享实例,然后拉了我的子视图宽度

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-03
        • 2013-12-27
        相关资源
        最近更新 更多