これは私が達成したいことです:
ユーザーがUIView2を上にスライドできるスライドアップアニメーションを実行したいのですが、UIView2は画面の途中で停止します。
私は次のようなUIButtonアクションを介してUIViewControlerをモーダルに提示する方法を知っています:
[self presentViewController:newController animated:NO completion:nil];
また、アニメーションにはこのタイプのコードが必要であることも知っています。
[UIView animateWithDuration:0.5f animations:^{
[self.customView layoutIfNeeded];
} completion:^(BOOL finished) {
}];
ただし、特にプロジェクトにAutoLayoutを使用し、制約を使用して複数の画面サイズを簡単にサポートしているため、UIViewsでこれを実現する方法がわかりません。
AutoLayoutと設定した制約を壊さずにこれを達成するにはどうすればよいですか?
ありがとう
この状況で私が通常行うことは次のとおりです。
シーンに2つのコンストレイントを追加します。一つUIView2
の底に整列されますUIView1
。2つ目は、中央に配置さUIView1
れています(ビュー間でCtrlキーを押しながらドラッグして、制約を適切に追加する必要があります)。これらの制約は最初は互いに競合しますが、それは問題ありません。
のIBOutlet
ビューコントローラにを追加し、NSLayoutConstraints
作成した2つの制約をそれらに割り当てIBOutlet
ます。
初期条件の制約優先度を999に設定します(つまり、下に揃える際の制約優先度は999である必要があります)。宛先制約の制約優先度を998に設定します(つまり、中央揃えの制約優先度は998です)。これで、これらの制約が競合しなくなることがわかります。これは、一方の制約の優先順位がもう一方の制約よりも優先されるためです。
あなたはこれが今どこに向かっているのかわかるかもしれません。したがってUIView2
、制約間でアニメーション化する場合は、優先順位を交換してアニメーション化します。
コード:
@interface MyViewController ()
@property (nonatomic, weak) IBOutlet NSLayoutConstraint* constraint0;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint* constraint1;
@end
- (void)someMethodWhereIWantToAnimate
{
NSInteger temp = self.constraint0.priority;
self.constraint0.priority = self.constraint1.priority;
self.constraint1.priority = temp;
[UIView animateWithDuration:0.3 animations:^{
// Simplest is to use the main ViewController's view
[self.view layoutIfNeeded];
}];
}
パンを有効にし、それを使用してアニメーションを開始するには、ビューコントローラーにパンジェスチャ認識機能を追加します。CtrlUIView2
キーを押しながらからPanGesture Recognizerにドラッグし、として設定しgestureRecognizer
ます。これで、をドラッグするとUIView2
、パンイベントを受信できるようになります。
パンを処理するためのIBActionを追加します。
- (IBAction)onPan:(id)sender
{
}
Ctrlキーを押しながらパンジェスチャレコグナイザーからビューコントローラーにドラッグしonPan:
、送信済みアクションとして設定します。
sender
実際には、パンジェスチャレコグナイザー自体です。したがって、このメソッドに入力してパンを処理UIView2
し、ユーザーの指の下をたどり、ユーザーが離したときにアニメーションを開始することができます。
コードの入力を始めましょう:
- (IBAction)onPan:(id)sender
{
UIPanGestureRecognizer* recognizer = (UIPanGestureRecognizer*)sender;
CGPoint translation = [recognizer translationInView:self.view];
NSLog(@"State: (%d) Translation in view: (%f, %f)", recognizer.state, translation.x, translation.y);
}
このコードで実行し、指を上UIView2
にドラッグすると、次のような出力が表示されます。
State: (1) Translation in view: (0.000000, -2.500000)
State: (2) Translation in view: (0.500000, -7.500000)
State: (2) Translation in view: (0.500000, -7.500000)
State: (2) Translation in view: (1.500000, -12.000000)
State: (2) Translation in view: (2.500000, -16.500000)
State: (2) Translation in view: (2.500000, -19.500000)
State: (2) Translation in view: (2.500000, -24.500000)
State: (2) Translation in view: (2.500000, -25.000000)
State: (2) Translation in view: (2.500000, -25.500000)
State: (2) Translation in view: (2.500000, -27.000000)
State: (2) Translation in view: (2.500000, -29.500000)
State: (2) Translation in view: (2.500000, -31.000000)
State: (2) Translation in view: (2.500000, -31.500000)
State: (3) Translation in view: (2.500000, -31.500000)
値が絶えず増加していることに注意してください。増分量が必要になります。ログの状態に注意してください。状態(1)はドラッグスタートです。状態(2)はドラッグ変更されます。状態(3)はドラッグ終了です。この情報を使用して、デルタを計算できます。
追加CGPoint
あなたのビューコントローラにプロパティを、同様IBOutletとしてUIView2を追加します。
@property (nonatomic) CGPoint lastTranslation;
@property (nonatomic, weak) IBOutlet UIView* uiView2;
最後に、パンメソッドの最終フォームに記入しましょう。
- (IBAction)onPan:(id)sender
{
UIPanGestureRecognizer* recognizer = (UIPanGestureRecognizer*)sender;
CGPoint delta;
switch(recognizer.state) {
case UIGestureRecognizerStateBegan:
// On state begin: delta is the translation. Store it in our member for later user.
self.lastTranslation = delta = [recognizer translationInView:self.view];
break;
case UIGestureRecognizerStateChanged:
// On state changed: calculate the difference between the translation and our
// previous translation.
delta = CGPointApplyAffineTransform([recognizer translationInView:self.view], CGAffineTransformMakeTranslation(-self.lastTranslation.x, -self.lastTranslation.y));
self.lastTranslation = [recognizer translationInView:self.view];
break;
case UIGestureRecognizerStateEnded:
// On state ended: Let's just do the constraint animation.
[self someMethodWhereIWantToAnimate];
break;
default:
break;
}
delta.x = 0; // Forces only vertical drag on the UIView2.
self.uiView2.center = CGPointApplyAffineTransform(self.uiView2.center, CGAffineTransformMakeTranslation(delta.x, delta.y)); // Move our uiView2 based on the delta.
NSLog(@"State: (%d) Translation in view: (%f, %f)", recognizer.state, delta.x, delta.y);
}
これでうまくいくはずです。パンジェスチャのvelocityInView:
方法に基づいて、制約のUIViewアニメーションを少し調整することを検討することもできますが、それは演習として残しておきます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加