1

私はiOS(6)アプリで作業しており、サイズを変更(アニメーション化)したビューがあり、そのビュー内にUILabelがあります。これは、ビューとともに拡大したいのですが、比例的には拡大しません。

つまり、ビューが特定のサイズの場合、たとえばビューの90%を占める必要がありますが、(別の特定のサイズに)大きくすると、80%などのビューのみを占めるようにします。これは、スーパービューが大きくなると表示されるUILabel周辺の他のサブビューに対応するためです。

これでNSLayoutContraintsを使用して、先頭のスペースを必要なサイズに設定し、UILabelの幅を設定して適切に拡大してみました。また、先頭と末尾のスペースを設定してみました(その後、幅は自動的に拡大します)。

奇妙なことに、同じアニメーションコードブロック(UIView animateWithDuration:...を使用)にNSLayoutContraintsを使用している他のサブビューがあり、それらはすべて機能します。ただし、これらはすべて間隔の制約であり、サイズの制約ではなく、UILabelが関係するものはないため、これがそれと関係があるかどうかはわかりません...

次に、UILabelのtranslatesAutoresizingMaskIntoConstraints = YESを設定し、ラベルにsetFrame:を使用してみました。これにより、ラベルのサイズと位置が正確に設定されますが、変更はアニメーション化されないため、ひどいように見えます...

他の誰かがこのようなことや私を助けるためのアイデアを経験したことがありますか?

ありがとう

以下は、私が試したコードです。ここで、「left」はラベルの先頭のスペース制約であり、「width」はラベルの幅制約です。

setFrameメソッドは、親ViewControllerからアニメーションコードブロック内で呼び出されます。

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];

    float gap = ((frame.size.height - 36) - 9 * [self.account.accountData numberOfBars]) / ([self.account.accountData numberOfBars] + 1);
    for (NSLayoutConstraint *constraint in constraints) {
        constraint.constant = gap;
    }

    self.left.constant = frame.size.width * 34/160 + (2 - 34 * 140 / 160);
    self.width.constant = frame.size.width * 0.575 + 55.5;

    [self layoutIfNeeded];

}
4

1 に答える 1

1

これは、constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: を使用してコードで実行できるはずです。乗数と定数を一緒に使用するとうまくいくはずです。ラベルの幅をそのスーパービューの幅と等しくなるように設定しますが、たとえば 0.7 または 0.8 の乗数と、ビューの小さいサイズで適切な幅を与える定数を使用します。ビューが大きくなるにつれて、その定数値は全体の幅のより小さい部分を構成します。たとえば、乗数が 0.7 で定数が 20 の場合、スーパービューの幅が 100 ポイントの場合、ラベルは 90 ポイント (100*.7 + 20) になります。ビューが 200 に拡大すると、ラベルは 160 幅 (またはスーパービューの 80%) になります。

編集後:

実際、上記の方法はうまくいかないと思います。WWDC 2012 の講演「自動レイアウトをマスターするためのベスト プラクティス」では、コア アニメーションの使用またはコンストレインを直接アニメーション化する方法について話しています。これは後者をしなければならないケースだと思います。コア アニメーションを使用すると、両方がアニメーション ブロック内にある場合でも、ビューのアニメーション中にラベルが新しいサイズにジャンプします (少なくとも私にとってはそうでした。Rob、よく知っている場合は投稿してください)。制約を (IOS で) 直接アニメーション化するには、タイマーを使用し、制約定数をインクリメントする必要があります。NSTimer を使用することもできますが、解像度の制限 (50 ~ 100 ミリ秒) のため、少しぎこちないことがわかりました。よりスムーズな方法は、ディスプレイのリフレッシュ レートに関連付けられている CADisplayLink を使用することです (16.7 ミリ秒だと思います)。だからここに私が使用したコードがあります。IB での私のセットアップは、170 幅のラベルが内側にある 190 幅のビューです。両方に幅の制約があります (これには QuartzCore フレームワークを追加する必要があります)。

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
@property (strong,nonatomic) CADisplayLink *displayLink;
@end

@implementation ViewController {

    IBOutlet NSLayoutConstraint *labelWidthCon;
    IBOutlet NSLayoutConstraint *viewWidthCon;
}


-(IBAction)startViewTimer:(id)sender {
    [self startDisplayLink];
}

-(void)startDisplayLink {
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(expandView:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink {
    [self.displayLink invalidate];
    self.displayLink = nil;
}


-(void)expandView:(CADisplayLink *) link {
    labelWidthCon.constant += 5;
    viewWidthCon.constant +=10;
    if (viewWidthCon.constant > 370) [self stopDisplayLink];
}
于 2013-02-10T01:07:28.280 に答える