web-dev-qa-db-fra.com

UIBarButtonItem: Comment trouver son cadre?

J'ai un bouton dans une barre d'outils. Comment puis-je saisir son cadre? UIBarButtonItems n'a-t-il pas une propriété frame?

60
totalitarian

Essaye celui-là;

UIBarButtonItem *item = ... ;
UIView *view = [item valueForKey:@"view"];
CGFloat width;
if(view){
    width=[view frame].size.width;
}
else{
    width=(CGFloat)0.0 ;
}
88
Anoop Vaidya

Cette façon fonctionne le mieux pour moi:

UIView *targetView = (UIView *)[yourBarButton performSelector:@selector(view)];
CGRect rect = targetView.frame;
19
MobileMon

Merci à Anoop Vaidya pour la réponse suggérée. Une alternative pourrait être (à condition de connaître la position du bouton dans la barre d’outils)

UIView *view= (UIView *)[self.toolbar.subviews objectAtIndex:0]; // 0 for the first item


CGRect viewframe = view.frame;
12
totalitarian

AvecSwift, si vous devez souvent utiliser des éléments de bouton de barre, vous devez implémenter une extension comme celle-ci:

extension UIBarButtonItem {

    var frame: CGRect? {
        guard let view = self.value(forKey: "view") as? UIView else {
            return nil
        }
        return view.frame
    }

}

Ensuite, dans votre code, vous pouvez accéder facilement:

if let frame = self.navigationItem.rightBarButtonItems?.first?.frame {
    // do whatever with frame            
}
8
Luca Davanzo

Oof, beaucoup de réponses brutes dans ce fil. Voici la bonne façon de le faire:

import UIKit

class ViewController: UIViewController {

    let customButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()

        customButton.setImage(UIImage(named: "myImage"), for: .normal)
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: customButton)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print(self.customButton.convert(self.customButton.frame, to: nil))
    }
}
5
Dan Stenmark
-(CGRect) getBarItemRc :(UIBarButtonItem *)item{
    UIView *view = [item valueForKey:@"view"];
    return [view frame];
}
2
Gank

Voici ce que j'utilise dans iOS 11 et Swift 4. Cela pourrait être un peu plus propre sans l'option mais je joue la sécurité:

extension UIBarButtonItem {
    var view: UIView? {
        return perform(#selector(getter: UIViewController.view)).takeRetainedValue() as? UIView
    }
}

Et utilisation:

if let barButtonFrame = myBarButtonItem.view?.frame {
    // etc...
}
2
jday

Essayez cette implémentation:

@implementation UIBarButtonItem(Extras)

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

Voici la bonne façon de le faire:

-(CGRect)findFrameOfBarButtonItem{
    for (UIView *view in self.navigationController.navigationBar.subviews)
    {
       if ([view isKindOfClass:NSClassFromString(@"_UINavigationBarContentView")])
       {
         UIView * barView = [self.navigationItem.rightBarButtonItem valueForKey:@"view"];
         CGRect barFrame = barView.frame;
         CGRect viewFrame = [barView convertRect:barFrame toView:view];
         return viewFrame;
       }
    }

    return CGRectZero;
}

dans Swift 4.2 et inspiré par luca

extension UIBarButtonItem {

    var frame:CGRect?{
        return (value(forKey: "view") as? UIView)?.frame
    }

}


guard let frame = self.navigationItem.rightBarButtonItems?.first?.frame else{ return }
0
Reimond Hill

Vous devez faire une boucle sur les sous-vues et vérifier leur type ou leur contenu afin d'identifier .. Il n'est pas sûr d'accéder à view by kvo et vous ne pouvez pas être sûr de l'index.

0
user4091416

Vous pouvez le calculer approximativement à l'aide des propriétés telles que layoutMargins et frame sur la barre de navigation, combinées aux guides de taille d'icône de Human Interface Guidelines et prendre en compte l'orientation actuelle du périphérique:

- (CGRect)rightBarButtonFrame {
    CGFloat imageWidth = 28.0;
    CGFloat imageHeight = UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeLeft || UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeRight ? 18.0 : 28.0;
    UIEdgeInsets navigationBarLayoutMargins = self.navigationController.navigationBar.layoutMargins;
    CGRect navigationBarFrame = self.navigationController.navigationBar.frame;
    return CGRectMake(navigationBarFrame.size.width-(navigationBarLayoutMargins.right + imageWidth), navigationBarFrame.Origin.y + navigationBarLayoutMargins.top, imageWidth, imageHeight);
}
0
turingtested

Vous pouvez créer un UIBarButtonItem avec une vue personnalisée, qui est un UIButton, puis vous pouvez faire ce que vous voulez. :]

0
Nix Wang

Regardez cette réponse: Comment appliquer des bordures et des rayons de coins à UIBarButtonItem? qui explique comment passer en revue les vues secondaires pour trouver le cadre d'un bouton.

0
frandogger