2010-12-28 9 views
1

私はUINavigationControllerを持っていて、スタックにポップされたすべてのView Controllerのビューに、 )。これを達成する最良の方法は何ですか?UINavigationController:すべてのポップされたView Controllerのビューに共通のパディング/マージンを適用する

私は元来、UINavigationControllerDelegateを実装でき、navigationController:didShowViewController:animatedまたはnavigationController:willShowViewController:animatedのメソッドの中に、表示しようとしていたビューコントローラのフレームを変更すると考えました。しかしこれは効果がないようです。

私はビューコントローラのviewDidAppearviewWillAppearメソッド内で同じことを試みましたが、これも機能しませんでした。理想的には、ナビゲーションコントローラ内で常に使用されるとは限らないため、コントローラにロジックを配置することは望ましくありません。

まだ試していない最後のアイデアは、実際にこのスタックにプッシュされる「ラッパー」UIViewControllerを作成することです。このラッパーは、実際のビューコントローラーのビューを、望みのマージンを提供するフレームを持つサブビューとして追加します。ここでの欠点は、UINavigationControllerをサブクラス化し、ラッパーを初期化してプッシュするpushViewController:animatedを上書きする必要があることです。 Appleのマニュアルには、UINavigationControllerはサブクラス化されていないことが示されています。

ありがとうございます。

+0

は、上記の "最後のアイデア" を実装しようとしましたが、暗礁に乗り上げます。表示されているビューコントローラは実際には別のビューコントローラによって「ラップ」されており、ラッパーは実際にスタックにプッシュされているため、表示されているビューコントローラのnavigationControllerプロパティは 'nil'です。これは、別のView Controllerを上に押し込むためにNavigation Controllerへのハンドルを取得できないことを意味します。 –

+0

別のデータポイント: 'navigationController:didShowViewController:animated'のビューコントローラのビューのフレームを実際に変更すると、実際には動作しますが、ビューコントローラは最初に元のフレームに表示され、事実の後にサイズが変更されます。しかし、「navigationController:willShowViewController:animated」のフレームを変更しても効果はありません。 –

答えて

1

UIViewControllerの代わりにUIViewControllerviewの周りに "ラッパー" UIViewを入れて解決しました。ラッパービューは、layoutSubviewsメソッドのサブビューのフレームを設定することによって、サブビューを埋め込みます。

私は便宜的に使用したコードを添付しました。使用するには、UINavigationControllerPaddedNavigationControllerに置き換え、PaddedNavigationControllerinsetsプロパティを設定します。

PaddedNavigationController.h

#import <Foundation/Foundation.h> 

@interface PaddedNavigationController : UINavigationController 
{ 
    UIEdgeInsets _insets; 
} 

@property (nonatomic, assign) UIEdgeInsets insets; 

@end 

PaddedNavigationController.m

#import "PaddedNavigationController.h" 

@interface PaddedView : UIView 
{ 
    UIView *_view; 
    UIEdgeInsets _insets; 
} 

@property (nonatomic, assign) UIEdgeInsets insets; 

+ (PaddedView *) wrapView:(UIView *)view withInsets:(UIEdgeInsets)insets; 
- (id) initWithView:(UIView *)view insets:(UIEdgeInsets)insets; 

@end 


@implementation PaddedNavigationController 

@synthesize insets = _insets; 

- (void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    //check if the UIViewController's view has already been wrapped by the PaddedView; don't want to wrap it twice 
    if(![viewController.view isKindOfClass:[PaddedView class]]) 
    { 
     viewController.view = [PaddedView wrapView:viewController.view withInsets:self.insets]; 
    } 
    [super pushViewController:viewController animated:animated]; 
} 

- (void) setInsets:(UIEdgeInsets)insets 
{ 
    _insets = insets; 

    //loop through this navigation controller's view controllers and set the new insets on any PaddedViews 
    for(UIViewController *viewController in self.viewControllers) 
    { 
     if([viewController.view isKindOfClass:[PaddedView class]]) 
     { 
      PaddedView *padded = (PaddedView *)viewController.view; 
      padded.insets = insets; 
     } 
    } 
} 

@end 


@implementation PaddedView 

@synthesize insets = _insets; 

+ (PaddedView *) wrapView:(UIView *)view withInsets:(UIEdgeInsets)insets 
{ 
    return [[[PaddedView alloc] initWithView:view insets:insets] autorelease]; 
} 

- (id) initWithView:(UIView *)view insets:(UIEdgeInsets)insets 
{ 
    if(self = [super initWithFrame:view.frame]) 
    { 
     _insets = insets; 
     self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
     _view = [view retain]; 
     [self addSubview:view]; 
    } 
    return self; 
} 

- (void) dealloc 
{ 
    [_view release]; 
    [super dealloc]; 
} 

- (void) layoutSubviews 
{ 
    //apply the insets to the subview 
    _view.frame = CGRectMake(self.insets.left, self.insets.top, self.frame.size.width - self.insets.left - self.insets.right, self.frame.size.height - self.insets.top - self.insets.bottom); 
} 

- (void) setInsets:(UIEdgeInsets)insets 
{ 
    _insets = insets; 
    //we need to re-layout the subviews as the insets have changed 
    [self layoutSubviews]; 
} 

@end 
+1

私はこれを試してみる機会がありませんでしたが、それはかなり良い解決策(少なくとも私が思い付く何かよりも良い)のように見えます。ありがとう! –

+0

この道路を降りた後、実際にはうまくいきません。あなたのビューコントローラは本当にビューがラップされているという事実に不可抗力ではありません。サブビューを追加しようとすると、サブビューの境界を決定するためにビューコントローラのビューの境界を使用すると、望ましくない結果になります。 –

+0

さらに、このアプローチはメモリ警告が発生し、ビューコントローラのビューが 'PaddedView'インスタンスでラップされずに再ロードされるときに問題になります。 –

関連する問題