新しい iOS の Google マップ アプリのスライド アップ メニューの動作を再現しようとしています。
つまり、基本的には、特定のポイントまでパンしてスライドアップしたり、特定のポイントまでスライドダウンしたりできるビューです。このビューは、ページ分割されたスクロール ビューのように左右にスライドすることもできます。
上下にスクロールするか、横にスライドする必要がありますが、両方を同時に行うことはできません。
多くの調査とテストの後、私は近いものを持っていますが、必要なほどうまく機能していません。
私の実装は、320x400 のフレームとページ分割されたスクロールを備えた 960x400 のコンテンツ ビューを持つ UIScrollView です。次に、ビュー全体のスライドアップを処理する UIPanGestureRecognizer を追加します。
PanRecognizer の handleTouch IBAction は次のとおりです。
- (IBAction)handlePan:(UIPanGestureRecognizer *)sender {
NSLog(@"Panning");
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
_firstX = [[sender view] center].x;
_firstY = [[sender view] center].y;
}
if (!IS_IPHONE_5) {
if (_firstY < 216)
translatedPoint = CGPointMake(_firstX, 216);
else
translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);
}
else {
if (_firstY < 307)
translatedPoint = CGPointMake(_firstX, 307);
else
translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);
}
[[sender view] setCenter:translatedPoint];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].y);
CGFloat finalX = _firstX;
CGFloat finalY = translatedPoint.y + velocityY;
if(finalY < _firstY) {
if (IS_IPHONE_5)
finalY = 307;
else
finalY = 216;
}
else if(finalY > _firstY) {
if (IS_IPHONE_5)
finalY = 605;
else
finalY = 515;
}
CGFloat animationDuration = (ABS(velocityY)*.0002)+.2;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidFinish)];
[[sender view] setCenter:CGPointMake(finalX, finalY)];
[UIView commitAnimations];
}}
したがって、基本的に、パンがビューを横ではなく上にスライドさせる場合。この handlePan メソッドで私が抱えている問題は、ポイントよりも高いスクロールを許可しないように機能させることができないことです。それは私がやろうとしていることです:
if (_firstY < 216)
translatedPoint = CGPointMake(_firstX, 216);
else
translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y);
考えられる最大の問題は、UIScrollView パン ジェスチャ レコグナイザーが、追加したパンと同時にパンを処理していることです。つまり、UIScrollView を指で上下にスライドさせて側面にも移動させると、UIScrollView が同時に上下にスライドされます。
側面のみにスライドしてビューを 1 ピクセル上に移動しようとすると、パン認識機能が終了し、ビューが完全に上にスライドします。
私が見つけた回避策は、パン認識エンジンを設定して、UIScrollview パン認識エンジンが機能しないようにすることです。
[_panGestureRecognizer requireGestureRecognizerToFail: _slideUpScrollView.panGestureRecognizer];
そのため、横にスライドしても機能し、ビューが上に移動しません。考えられる問題は、指を離したときにのみ失敗として設定され、ビューが横にスクロールしなかったことです。ビューを上にパンすることはできませんが、内部をフリックすると、「UIGestureRecognizerStateEnded」になり、ビューが上にスライドします。
私は UIPanGestureRecognizer のトピックを調べ、いくつかのオプションを調べました。たとえば、パン認識エンジンをサブクラス化して、スライドアップ パンのみを認識させ、サイド パンは認識させないようにしました。
私は正しい戦略を使用していると思いますか、それとも別の見方をする必要がありますか?
理想的な解決策は、横へのスライドが記録されている場合、コンテンツを水平方向にのみ移動し、UIScrollView によって処理され、水平方向のパンが記録されている場合、垂直方向にのみパンし、私の panreconizer によって処理されることです。水平および垂直スクロールでの Safari の動作と同じです。私はそれを実装する方法を理解していませんでしたが。
読んでくれてありがとう、あなたの考えを教えてください。多くのアプリに Google マップのようなスライド アップ メニューがあればいいのにと思います。
編集:iOS 6をターゲットにしています。