2

私は、多くのサブビューを含むカスタムUIViewのフレームを設定するためにどの方法を使用するかというジレンマに陥っていますが、それでもアニメーションがあり、回転に自動的に調整されます。新しいビューコントローラを作成するときに通常行うことは、loadViewまたはviewDidLoadでカスタムビューを割り当てることです。例:

-(void)viewDidLoad
{
    [super viewDidLoad];
    detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 0,      self.view.frame.size.width, self.view.frame.size.height)];
    detailView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
    self.view = detailView;    
}

通常、この幅と高さはiPhone5画面では正しくありません(実際のビューフレームはviewWillAppearまで設定されません)が、自動サイズ変更マスクがあるため、すべてうまくいきます。

次に、カスタムUIView DetailViewのinitWithFrameで、すべてのサブビューをCGRectZeroに割り当てます。例:

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        label = [[UILabel alloc] initWithFrame:CGRectZero];
        [self addSubview:label];
    }
 }

次に、layoutsubviewsをオーバーライドして、すべてのサブビューのすべてのフレームを設定します。これは、あらゆる画面サイズとあらゆる向きで完全に機能します。例:

-(void)layoutSubviews
{
    [super layoutSubviews];
    label.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
}

ただし、アニメーションを使用する場合、layoutSubviewsはそれほど優れていないことがわかりました。これは、animationblockでアニメーションを使用すると、layoutsubviewsがアニメーションの途中で呼び出され、アニメーションが完全に壊れてしまうためです。

-(void)animateLabel
{
    [UIView animateWithDuration:0.4f animations:^
    {
        label.transform = CGAffineTransformMakeTranslation(100, 100);
    }];
}

各アニメーションにフラグを使用することでこれを回避する醜い回避策があると思います。レイアウトサブビューでは、これらのフラグを使用してアニメーションブロックの正しい開始フレームまたは終了フレームを設定しますが、実行したいアニメーションごとにフラグを作成する必要はないと思います。 。

だから私の問題は今です:回転に合わせて自動的に調整されるアニメーション付きのカスタムUIViewをどのように持つべきですか?

私が今思いつくことができる唯一の解決策(私は好きではありません):layoutSubviewsを使用せずに、カスタムUIViewのsetFrame / setBoundsメソッドを使用して、すべてのサブビューのフレームを設定します。次に、回転が発生するたびにviewControllerをチェックインし、カスタムUIViewのsetFrame / setBoundsメソッドを使用して、すべてのサブビューのすべてのフレームを変更します。iOS5とiOS6では回転方法が異なり、独自のカスタムUIViewを使用するすべてのUIViewControllerでこれを行う必要がないため、このソリューションは好きではありません。

助言がありますか?

4

1 に答える 1

0

最近、でオーバーライドを開始しましたviewDidLayoutSubviews(の代わりに何度もviewWillAppearUIViewControllers

はいviewDidLayoutSubviewsはローテーションで呼び出されます。(コメントより)

このメソッドは、すべての内部レイアウトが完了した後に起動するため、完成したすべてのフレームを設定する必要がありますが、ビューが表示される前に調整を行うために必要な時間を確保でき、アニメーションに問題がないはずです。すでにアニメーションブロック内にあります。

viewcontroller.m

- (void)viewDidLayoutSubViews {
    // At this point I know if an animation is appropriate or not.
    if (self.shouldRunAnimation)
        [self.fuView runPrettyAnimations];
}

fuView.m

- (void)runPrettyAnimations {
    // My animation blocks for whatever layout I'd like.
}

- (void)layoutSubviews {
    // My animations are not here, but non animated layout changes are.
    // - Here we have no idea if our view is visible to the user or may appear/disappear
    // partway through an animation.
    // - This also might get called far more than we intend since it gets called on
    // any frame updates.
}
于 2013-03-25T12:38:02.593 に答える