ツールバーにボタンがあります。どうすればそのフレームをつかむことができますか?プロパティがありませUIBarButtonItem
んか?frame
15 に答える
これを試してください。
UIBarButtonItem *item = ... ;
UIView *view = [item valueForKey:@"view"];
CGFloat width;
if(view){
width=[view frame].size.width;
}
else{
width=(CGFloat)0.0 ;
}
この方法は私にとって最適です:
UIView *targetView = (UIView *)[yourBarButton performSelector:@selector(view)];
CGRect rect = targetView.frame;
Swiftでは、バーボタンアイテムを頻繁に操作する必要がある場合は、次のような拡張機能を実装する必要があります。
extension UIBarButtonItem {
var frame: CGRect? {
guard let view = self.value(forKey: "view") as? UIView else {
return nil
}
return view.frame
}
}
次に、コードで簡単にアクセスできます。
if let frame = self.navigationItem.rightBarButtonItems?.first?.frame {
// do whatever with frame
}
ああ、このスレッドには大まかな答えがたくさんあります。これを行う正しい方法は次のとおりです。
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))
}
}
提案された答えをくれたAnoopVaidyaに感謝します。別の方法として、(ツールバーのボタンの位置がわかっている場合)
UIView *view= (UIView *)[self.toolbar.subviews objectAtIndex:0]; // 0 for the first item
CGRect viewframe = view.frame;
これが私がiOS11とSwift4で使用しているものです。オプションがないと少しきれいになるかもしれませんが、安全にプレイしています。
extension UIBarButtonItem {
var view: UIView? {
return perform(#selector(getter: UIViewController.view)).takeRetainedValue() as? UIView
}
}
そして使用法:
if let barButtonFrame = myBarButtonItem.view?.frame {
// etc...
}
編集:これを使用することはもうお勧めしません。ダンの答えのように、カスタムビューでUIBarButtonItemsを使用するように実装を変更することになりました
-(CGRect) getBarItemRc :(UIBarButtonItem *)item{
UIView *view = [item valueForKey:@"view"];
return [view frame];
}
UIButtonであるカスタムビューを使用してUIBarButtonItemを作成すると、必要な操作を実行できます。:]
ヒューマンインターフェイスガイドラインlayoutMargins
のアイコンサイズガイドとframe
組み合わせて、navigationBarのようなプロパティを使用して大まかに計算し、現在のデバイスの向きを考慮に入れることができます。
- (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);
}
この実装を試してください:
@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
サブビューをループして、サブビューのタイプまたは内容を確認して識別できるようにする必要があります。kvoでビューにアクセスするのは安全ではなく、インデックスについて確信が持てません。
この回答を確認してください:UIBarButtonItemに境界線とコーナー半径を適用する方法は?これは、サブビューをループしてボタンのフレームを見つける方法を説明しています。
Swift 4.2で、lucaに触発されました
extension UIBarButtonItem {
var frame:CGRect?{
return (value(forKey: "view") as? UIView)?.frame
}
}
guard let frame = self.navigationItem.rightBarButtonItems?.first?.frame else{ return }
ビューにタグが付いたバーボタンアイテムのビューを使用しました。
for view in bottomToolbar.subviews {
if let stackView = view.subviews.filter({$0 is UIStackView}).first {
//target view has tag = 88
if let targetView = stackView.subviews.filter({$0.viewWithTag(88) != nil}).first {
//do something with target view
}
}
}
Swift 4 up現在の最善の方法は、次の場所からフレームにアクセスすることです。
self.navigationItem.rightBarButtonItems
に
let customView = navigationItem.rightBarButtonItems?.first?.customView // access the first added customView
この方法でアクセスする方が、プライベートAPIにアクセスするよりも安全です。
- これで答えをチェックしてください: