Как получить ширину UITabBarItem?

ширина UITabBarItem варьируется, в зависимости от того, сколько есть.

как определить, насколько широки мои элементы панели вкладок?

Я ищу свойство, если это возможно, в отличие от математической формулы, так как на iPad также есть проблема заполнения по обе стороны панели вкладок. Рассмотрим эти скриншоты. Обратите внимание на заполнение с обеих сторон элементов панели вкладок на iPad (выделено красными полями). Эта обивка не существует на iPhone.

iPad:

enter image description here

в iPhone: enter image description here

7 ответов


редактировать: в комментариях ниже было отмечено, что это решение не работает в бета-версии iOS 5, поэтому будьте готовы изменить его для удовлетворения ваших потребностей.

Я думаю, чтобы сделать это правильно, вы должны иметь возможность добраться до рамки каждого элемента панели вкладок. К счастью, это возможно:

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 середины выбранного элемента вкладки. От здесь вы можете добавить представление индикатора в представление контроллера панели вкладок относительно этой точки.

отказ от ответственности: опасность при таком подходе заключается в том, что он заглядывает под капот UITabBar класс, обратившись к его иерархии представлений и frame свойство экземпляров private UITabBarButton класса. Возможно (однако маловероятно), что этот подход может быть затронут/нарушен будущим обновлением iOS. Однако вы не получаете доступа к частным API, поэтому это не должно получить ваше приложение отклонено из App Store.

Я простой проект iPad, демонстрирующий, как он работает, в комплекте с анимацией.


uitabbaritem наследует от 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);

мне также интересно узнать, находит ли кто-то простое свойство, чтобы дать эту информацию.


глядя на ответ выше:

  1. элементов UITabBar работа различная в iPhone и iPad. В iPhone они заполняют всю ширину, в iPad они центрированы по горизонтали.
  2. существует интервал между элементами в iPad.
  3. вы можете установить значения для ширины и расстояния с помощью tabBar.itemWidth или tabBar.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))];

я попробовал эти 2 свойства 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;

но получите нулевое значение, как сказал 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? Потому что есть пробелы между кнопками панели вкладок. :)


вы можете получить вид tabBarItem с помощью частной собственности view. Потом просто сделать вид frame.

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

Swift 3

Я создал общий экземпляр в UIApplication, затем вытащил ширину моих подвидов

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


просмотрите подвиды таббара и найдите представления с классом "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
    }
}