/ / Wyliczyć ramkę UIBarButtonItem w oknie? - iPhone, Object-C, Cocoa-Touch, Uikit

Wyobraź sobie ramkę UIBarButtonItem w oknie? - iphone, cel-c, dotyk kakao, uikit

UIBarButtonItem nie rozszerza się UIView, więc nie ma nic takiego jak właściwość ramki.

Ale czy jest jakiś sposób, aby uzyskać to, co to jest CGRect ramka w stosunku do aplikacji UIWindow?

Odpowiedzi:

125 dla odpowiedzi nr 1

Czy lubisz korzystać? prywatne APIs Jeśli tak,

UIView* view = thatItem.view;
return [view convertRect:view.bounds toView:nil];

Oczywiście nikt nie chce tego podczas celowania w AppStore. ZA bardziej zawodny Metoda, a także wykorzystuje nieudokumentowane funkcje, ale przejdzie test Apple'a, polega na zapętleniu widoków podrzędnych w celu znalezienia odpowiedniego elementu przycisku.

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

The index jest indeksem elementu paska w tablicy .items, po usunięciu wszystkich pustych elementów. To zakłada przyciski są ułożone w porządku rosnącym, co może nie być. Bardziej niezawodną metodą jest sortować temu buttons tablica rośnie .origin.x wartość. Oczywiście, że nadal zakłada element przycisku paska musi dziedziczyć klasę UIControl i są bezpośrednimi widokami podrzędnymi paska narzędzi / paska nawigacyjnego, co również może nie być.


Jak widać, w przypadku nieudokumentowanych funkcji istnieje duża niepewność. Chcesz po prostu wyskoczyć coś pod palcem, prawda? UIBarButtonItem "s .action może być selektorem formularza:

-(void)buttonClicked:(UIBarButtonItem*)sender event:(UIEvent*)event;

zanotuj zdarzenie argument - możesz uzyskać pozycję dotyku

[[event.allTouches anyObject] locationInView:theWindow]

lub widok przycisku za pomocą

[[event.allTouches anyObject] view]

Dlatego nie ma potrzeby iteracji podglądów podrzędnych ani używania nieudokumentowanych funkcji do tego, co chcesz zrobić.


16 dla odpowiedzi nr 2

Nie widziałem opublikowanej tej opcji (co moim zdaniem jest znacznie prostsze), więc oto jest:

UIView *barButtonView = [barButtonItem valueForKey:@"view"];

8 dla odpowiedzi nr 3

W iOS 3.2 jest znacznie łatwiejszy sposób na wyświetlenie wyskakującego arkusza akcji z przycisku paska narzędzi. Wystarczy zrobić coś takiego:

- (IBAction)buttonClicked:(UIBarButtonItem *)sender event:(UIEvent *)event
{
UIActionSheet *popupSheet;
// Prepare your action sheet
[popupSheet showFromBarButtonItem:sender animated:YES];
}

4 dla odpowiedzi № 4

Oto implementacja, której używam w moim projekcie 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

2 dla odpowiedzi № 5

Udało mi się uruchomić WEpopover Wernera Altewischera, przekazując pasek narzędzi wraz z
UIBarButton: Mod znajduje się w 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];
}

2 dla odpowiedzi № 6

Tak długo jak UIBarButtonItem (i UITabBarItem) nie dziedziczy z UIView—Z powodów historycznych UIBarItem dziedziczy z NSObject- to szaleństwo trwa (w chwili pisania tego tekstu, iOS 8.2 i wciąż rośnie ...)

Najlepsza odpowiedź w tym wątku jest oczywiście @KennyTM ”s. Nie wygłupiaj się i użyj prywatnego interfejsu API, aby znaleźć widok.

Oto rozwiązanie online Swift umożliwiające uzyskanie pliku origin.x posortowana tablica (np Odpowiedź Kenny'ego wskazuje):

    let buttonFrames = myToolbar.subviews.filter({
$0 is UIControl
}).sorted({
$0.frame.origin.x < $1.frame.origin.x
}).map({
$0.convertRect($0.bounds, toView:nil)
})

Tablica jest teraz origin.x posortowane z UIBarButtonItem ramki.

(Jeśli czujesz potrzebę przeczytania więcej o problemach innych ludzi z UIBarButtonItem, polecam Ash Furrow ”s post na blogu z 2012 roku: Odkrywanie UIBarButtonItem)


2 dla odpowiedzi № 7
-(CGRect) getBarItemRc :(UIBarButtonItem *)item{
UIView *view = [item valueForKey:@"view"];
return [view frame];
}

1 dla odpowiedzi № 8

Możesz go pobrać z widoku UINavigationBar. NavigationBar to UIView, który ma 2 lub 3 niestandardowe subviews za części na pasku.

Jeśli wiesz, że element UIBarButtonItem jest obecnie wyświetlany na pasku nawigacyjnym po prawej stronie, możesz pobrać jego ramkę z tablicy widoków podrzędnych navbar.

Najpierw potrzebujesz Pasek nawigacyjny które możesz uzyskać z navigationController które można pobrać z UIViewController. Następnie znajdź najbardziej odpowiedni widok podrzędny:

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

Nie skompilowałem tego kodu, więc YMMV.


0 dla odpowiedzi № 9

To nie jest najlepsze rozwiązanie iz pewnego punktu widzenia nie jest to właściwe rozwiązanie i nie możemy podążać za nim, ponieważ mamy dostęp do obiektu w środku UIBarBattonItem niejawnie, ale możesz spróbować zrobić coś takiego:

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

w rezultacie otrzymałem następny:

punkt {289, 22}

wprowadź opis obrazu tutaj


-1 dla odpowiedzi № 10

Przed zaimplementowaniem tego kodu koniecznie zadzwoń [window makeKeyAndVisible] w swoim delegacie Applition application:didFinishLaunchingWithOptions: metoda!

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

-1 dla odpowiedzi № 11

Zrobiłem to w następujący sposób:

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