2013-10-07 10 views
17

UIButtonをカスタムビューとして作成すると、他の多くのユーザーが同じ問題が発生しています。カスタムUIBarButtonItemとiOS7とのアライメント

基本的に、ボタンは左右に約10ピクセルです。カスタムビューなしで通常のBarButtonItemを使用すると、これは発生しません。

この投稿は、部分的なソリューションを提供する:ここでは UIBarButton With Custom View

は、私はUIButtonをサブクラス化して作成している私のコードである(他のポストで述べたように)

- (UIEdgeInsets)alignmentRectInsets { 
    UIEdgeInsets insets; 
    if ([self isLeftButton]) { 
     insets = UIEdgeInsetsMake(0, 9.0f, 0, 0); 
    } 
    else { // IF ITS A RIGHT BUTTON 
     insets = UIEdgeInsetsMake(0, 0, 0, 9.0f); 
    } 
    return insets; 
} 


- (BOOL)isLeftButton { 
    return self.frame.origin.x < (self.superview.frame.size.width/2); 
} 

これは素晴らしい作品が、私はポップときナビゲーションコントローラからのビューコントローラをこのメインビューに戻すと、ボタンはまだ約0.3秒間間違った位置に置かれ、正しい挿入図にスナップされます。

これは巨大な目障りなので、どうしてこのようにスナップして止めるのか分かりません。何かご意見は?ありがとう!

答えて

53

私はあなたや他の多くの人と同じ問題がありました。それを修正しようとしている長い時間の後、やっと私はそれをやった。これは、* -Prefix.pchファイルに含める必要があるカテゴリです。それだけです!

UINavigationItem + iOS7Spacing.h

#import <Foundation/Foundation.h> 
@interface UINavigationItem (iOS7Spacing) 
@end 

UINavigationItem + iOS7Spacing.m

#import "UINavigationItem+iOS7Spacing.h" 
#import <objc/runtime.h> 

@implementation UINavigationItem (iOS7Spacing) 

- (BOOL)isIOS7 
{ 
    return ([[[UIDevice currentDevice] systemVersion] compare:@"7" options:NSNumericSearch] != NSOrderedAscending); 
} 

- (UIBarButtonItem *)spacer 
{ 
    UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 
    space.width = -11; 
    return space; 
} 

- (void)mk_setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem 
{ 
    if ([self isIOS7] && leftBarButtonItem) { 
     [self mk_setLeftBarButtonItem:nil]; 
     [self mk_setLeftBarButtonItems:@[[self spacer], leftBarButtonItem]]; 
    } else { 
     [self mk_setLeftBarButtonItem:leftBarButtonItem]; 
    } 
} 

- (void)mk_setLeftBarButtonItems:(NSArray *)leftBarButtonItems 
{ 
    if ([self isIOS7] && leftBarButtonItems && leftBarButtonItems.count > 0) { 

     NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:leftBarButtonItems.count + 1]; 
     [items addObject:[self spacer]]; 
     [items addObjectsFromArray:leftBarButtonItems]; 

     [self mk_setLeftBarButtonItems:items]; 
    } else { 
     [self mk_setLeftBarButtonItems:leftBarButtonItems]; 
    } 
} 

- (void)mk_setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem 
{ 
    if ([self isIOS7] && rightBarButtonItem) { 
     [self mk_setRightBarButtonItem:nil]; 
     [self mk_setRightBarButtonItems:@[[self spacer], rightBarButtonItem]]; 
    } else { 
     [self mk_setRightBarButtonItem:rightBarButtonItem]; 
    } 
} 

- (void)mk_setRightBarButtonItems:(NSArray *)rightBarButtonItems 
{ 
    if ([self isIOS7] && rightBarButtonItems && rightBarButtonItems.count > 0) { 

     NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:rightBarButtonItems.count + 1]; 
     [items addObject:[self spacer]]; 
     [items addObjectsFromArray:rightBarButtonItems]; 

     [self mk_setRightBarButtonItems:items]; 
    } else { 
     [self mk_setRightBarButtonItems:rightBarButtonItems]; 
    } 
} 

+ (void)mk_swizzle:(SEL)aSelector 
{ 
    SEL bSelector = NSSelectorFromString([NSString stringWithFormat:@"mk_%@", NSStringFromSelector(aSelector)]); 

    Method m1 = class_getInstanceMethod(self, aSelector); 
    Method m2 = class_getInstanceMethod(self, bSelector); 

    method_exchangeImplementations(m1, m2); 
} 

+ (void)load 
{ 
    [self mk_swizzle:@selector(setLeftBarButtonItem:)]; 
    [self mk_swizzle:@selector(setLeftBarButtonItems:)]; 
    [self mk_swizzle:@selector(setRightBarButtonItem:)]; 
    [self mk_swizzle:@selector(setRightBarButtonItems:)]; 
} 

@end 

UINavigationItem+iOS7Spacing category on GitHub

+0

これは、UIEdegeInsetの変更よりも優れた解決策であると考えています。これにはタップ領域の問題はありません。 – Nick

+0

非常に良い!これも私の問題を解決しました! – rockstarberlin

+0

完璧なソリューション。もし私がそれを10回upvoteすることができます。 – kufi

4

ないマリウスの答えからサブクラス化UIButtonまたは方法スウィズリングの大ファン:https://stackoverflow.com/a/19317105/287403

私はちょうど単純なラッパーを使い、正しい位置を見つけるまで、ボタンのフレームのxを負の方向に動かしました。ボタンのタップも問題なく表示されます(ただし、必要に応じて、負のオフセットに合わせてボタンの幅を広げることもできます)。

は、ここで私は新しいバックボタンを生成するために使用するコードです:

- (UIBarButtonItem *) newBackButton { 
    // a macro for the weak strong dance 
    @weakify(self); 
    UIButton *backButton = [[UIButton alloc] init]; 
    [backButton setTitle:@"Back" forState:UIControlStateNormal]; 
    backButton.titleLabel.font = [UIFont systemFontOfSize:17]; 
    CGFloat width = [@"Back" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:nil].size.width + 27; 
    backButton.frame = CGRectMake(-17.5, 0, width + 17.5, 44); 
    [backButton setImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] forState:UIControlStateNormal]; 
    [backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 14, 0, 0)]; 
    [backButton setTitleColor:mTCOrangeColor forState:UIControlStateNormal]; 
    backButton.contentEdgeInsets = UIEdgeInsetsZero; 
    backButton.imageEdgeInsets = UIEdgeInsetsZero; 
    [backButton addEventHandler:^(id sender) { 
     // a macro for the weak strong dance 
     @strongify(self); 
     // do stuff here 
    } forControlEvents:UIControlEventTouchUpInside]; 
    UIView *buttonWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)]; 
    [buttonWrapper addSubview:backButton]; 
    return [[UIBarButtonItem alloc] initWithCustomView:buttonWrapper]; 
} 
+0

これは私のために働く唯一の解決策であり、UIButtonをサブビュー(+1)として使用するそれぞれのソリューションになります – Yossi

0

私は複数のnavigationBarButton項目にこのコードを試していないが、それは、単一のボタンのために働いているようです。私はUINavigationBarとそのlayoutSubviewsメソッドをオーバーライドしました。

まず、水平オフセットの定数がファイルの先頭に定義されます。 、あなたは右のサブビューのためのカスタムビュー(左サブビューについて-5、+5の内容のフレームを調整することができますまた

- (void)layoutSubviews{ 

    [super layoutSubviews]; 

    //Do nothing on iOS6 
    if (![[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f){return;} 

    UINavigationItem * navigationItem = [self topItem]; 

    for(UIBarButtonItem * item in [navigationItem rightBarButtonItems]){ 

     UIView * subview = [item customView]; 
     CGFloat width = CGRectGetWidth(subview.frame); 

     CGRect newRightButtonRect = CGRectMake(CGRectGetWidth(self.frame) - width - kNavBarButtonHorizontalOffset, 
              CGRectGetMinY(subview.frame), 
              width, 
              CGRectGetHeight(subview.frame)); 
     [subview setFrame:newRightButtonRect]; 

    } 

    for(UIBarButtonItem * item in [navigationItem leftBarButtonItems]){ 
     UIView * subview = [item customView]; 
     CGRect newRightButtonRect = CGRectMake(kNavBarButtonHorizontalOffset, 
              CGRectGetMinY(subview.frame), 
              CGRectGetWidth(subview.frame), 
              CGRectGetHeight(subview.frame)); 

     [subview setFrame:newRightButtonRect]; 
    } 
} 
0

static CGFloat const kNavBarButtonHorizontalOffset = 10; 

layoutSubviews:変更は、あなたが望むようです)、そしてあなたのカスタムビューががYESに設定されていない限り、それらは尊重されます。それは最もクリーンではありませんが、他の提案されたソリューションは、さらにハッキーなIMOになる可能性があります。

サブビューはIBでは5ポイントで表示されますが、シミュレータでアプリを実行するとコンテンツ全体が表示されます。

関連する問題