Выясните, кадр UIBarButtonItem в окне?
UIBarButtonItem
не расширяет UIView
, поэтому нет ничего похожего на свойство frame.
Но можно ли каким-либо образом получить, что это за CGRect
, относительно приложения UIWindow
?
- Поиск расстояния от значения RSSI устройства Bluetooth с низким энергопотреблением
- Добавление изображений в UITextView
- Выполнение команд оболочки с помощью NSTask - Objective-C Cocoa
- iOS8 - ограничения двусмысленно указывают на высоту нуля
- Как проспать от сна программно, если крышка закрыта?
- drawRect не вызывается в моем подclassе UIImageView
- Преобразование миллисекунд в NSDate
- Как правильно представить popover из UITableViewCell с помощью UIPopoverArrowDirectionRight или UIPopoverArrowDirectionLeft
- Получить текущего первого ответчика без использования частного API
- Перемещение фигуры Stick, опорных точек, анимации или чего-то еще ...?
- Могу ли я делать запросы POST или GET из приложения iphone?
- Программно включить Bluetooth в iphone sdk?
- Ошибка Apple Mach-O Linker при компиляции для устройства
Вы любите использовать частные API ? Если да,
UIView* view = thatItem.view; return [view convertRect:view.bounds toView:nil];
Конечно, никто не хочет этого, ориентируясь на AppStore. Более ненадежный метод, а также использует недокументированные функции, но будет проходить тест Apple, заключается в том, чтобы перебирать подпункты для поиска соответствующего элемента кнопки.
NSMutableArray* buttons = [[NSMutableArray alloc] init]; for (UIControl* btn in theToolbarOrNavbar.subviews) if ([btn isKindOfClass:[UIControl class]]) [buttons addObject:btn]; UIView* view = [buttons objectAtIndex:index]; [buttons release]; return [view convertRect:view.bounds toView:nil];
index
является индексом вашего элемента bar в массиве .items
, после удаления всех пустых элементов . Это предполагает, что кнопки расположены в порядке возрастания, чего может и не быть. Более надежным методом является сортировка массива buttons
при увеличении значения .origin.x
. Конечно, это по-прежнему предполагает, что элемент кнопки панели должен наследовать class UIControl и является прямым подзоном панели инструментов / навигационной панели, чего может и не быть.
Как вы можете видеть, существует много неопределенности при работе с недокументированными функциями. Однако, вы просто хотите что-то всплыть под пальцем? Операция .action
может быть селектором формы:
-(void)buttonClicked:(UIBarButtonItem*)sender event:(UIEvent*)event;
обратите внимание на аргумент события – вы можете получить позицию касания с
[[event.allTouches anyObject] locationInView:theWindow]
или вид кнопки с
[[event.allTouches anyObject] view]
Поэтому нет необходимости перебирать подпункты или использовать недокументированные функции для того, что вы хотите сделать.
Я не видел, чтобы этот вариант был опубликован (что, на мой взгляд, намного проще), так вот:
UIView *barButtonView = [barButtonItem valueForKey:@"view"];
В iOS 3.2 есть гораздо более простой способ показать всплывающее окно Action Sheet с панели инструментов. Просто сделайте что-нибудь вроде этого:
- (IBAction)buttonClicked:(UIBarButtonItem *)sender event:(UIEvent *)event { UIActionSheet *popupSheet; // Prepare your action sheet [popupSheet showFromBarButtonItem:sender animated:YES]; }
Это реализация, которую я использую для моего проекта WEPopover: ( https://github.com/werner77/WEPopover ):
@implementation UIBarButtonItem(WEPopover) - (CGRect)frameInView:(UIView *)v { UIView *theView = self.customView; if (!theView.superview && [self respondsToSelector:@selector(view)]) { theView = [self performSelector:@selector(view)]; } UIView *parentView = theView.superview; NSArray *subviews = parentView.subviews; NSUInteger indexOfView = [subviews indexOfObject:theView]; NSUInteger subviewCount = subviews.count; if (subviewCount > 0 && indexOfView != NSNotFound) { UIView *button = [parentView.subviews objectAtIndex:indexOfView]; return [button convertRect:button.bounds toView:v]; } else { return CGRectZero; } } @end
Я смог заставить WEpopover Вернера Алтевиша работать, пропустив панель инструментов вместе с
UIBarButton: Mod находится в WEPopoverController.m
- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item toolBar:(UIToolbar *)toolBar permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated { self.currentUIControl = nil; self.currentView = nil; self.currentBarButtonItem = item; self.currentArrowDirections = arrowDirections; self.currentToolBar = toolBar; UIView *v = [self keyView]; UIButton *button = nil; for (UIView *subview in toolBar.subviews) { if ([[subview class].description isEqualToString:@"UIToolbarButton"]) { for (id target in [(UIButton *)subview allTargets]) { if (target == item) { button = (UIButton *)subview; break; } } if (button != nil) break; } } CGRect rect = [button.superview convertRect:button.frame toView:v]; [self presentPopoverFromRect:rect inView:v permittedArrowDirections:arrowDirections animated:animated]; }
Пока UIBarButtonItem
(и UITabBarItem
) не наследуется от UIView
– по историческим причинам UIBarItem
наследуется от NSObject
– это безумие продолжается ( UIBarItem
с этой записи, iOS 8.2 и подсчета …)
Лучший ответ в этой теме – это, очевидно, @ KennyTM . Не будьте глупыми и используйте частный API, чтобы найти представление.
Вот решение oneline Swift, чтобы получить отсортированный массив origin.x
(как подсказывает Кенни ):
let buttonFrames = myToolbar.subviews.filter({ $0 is UIControl }).sorted({ $0.frame.origin.x < $1.frame.origin.x }).map({ $0.convertRect($0.bounds, toView:nil) })
Массив теперь origin.x
сортируется с кадрами UIBarButtonItem
.
(Если вы считаете, что вам нужно больше узнать о борьбе других людей с UIBarButtonItem, я рекомендую сообщение блога Ash Furrow с 2012 года: Изучение UIBarButtonItem )
-(CGRect) getBarItemRc :(UIBarButtonItem *)item{ UIView *view = [item valueForKey:@"view"]; return [view frame]; }
Вы можете получить его из представления UINavigationBar. NavigationBar – это UIView, у которого есть 2 или 3 пользовательских поднабора для частей на панели.
Если вы знаете, что UIBarButtonItem в настоящее время отображается в навигационной панели справа, вы можете получить его фрейм из массива subviews navbar.
Сначала вам понадобится навигационная панель, которую вы можете получить от навигационного controllerа, который вы можете получить от UIViewController. Затем найдите правильное подзапрос:
UINavigationBar* navbar = curViewController.navigationController.navigationBar; UIView* rightView = nil; for (UIView* v in navbar.subviews) { if (rightView==nil) { rightView = v; } else if (v.frame.origin.x > rightView.frame.origin.x) { rightView = v; // this view is further right } } // at this point rightView contains the right most subview of the navbar
Я не скомпилировал этот код так YMMV.
Это не лучшее решение, и с некоторой точки зрения это неправильное решение, и мы не можем делать этого, потому что мы неявно обращаемся к объекту внутри UIBarBattonItem
, но вы можете попытаться сделать что-то вроде:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; [button setImage:[UIImage imageNamed:@"Menu_Icon"] forState:UIControlStateNormal]; [button addTarget:self action:@selector(didPressitem) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:button]; self.navigationItem.rightBarButtonItem = item; CGPoint point = [self.view convertPoint:button.center fromView:(UIView *)self.navigationItem.rightBarButtonItem]; //this is like view because we use UIButton like "base" obj for //UIBarButtonItem, but u should note that UIBarButtonItem base class //is NSObject class not UIView class, for hiding warning we implicity //cast UIBarButtonItem created with UIButton to UIView NSLog(@"point %@", NSStringFromCGPoint(point));
в результате я получил следующее:
точка {289, 22}
Перед выполнением этого кода обязательно вызовите [window makeKeyAndVisible]
в приложении делегирования application:didFinishLaunchingWithOptions:
method!
- (void) someMethod { CGRect rect = [barButtonItem convertRect:barButtonItem.customview.bounds toView:[self keyView]]; } - (UIView *)keyView { UIWindow *w = [[UIApplication sharedApplication] keyWindow]; if (w.subviews.count > 0) { return [w.subviews objectAtIndex:0]; } else { return w; } }
Я обработал его следующим образом:
- (IBAction)buttonClicked:(UIBarButtonItem *)sender event:(UIEvent *)event { UIView* view = [sender valueForKey:@"view"]; //use KVO to return the view CGRect rect = [view convertRect:view.bounds toView:self.view]; //do stuff with the rect }