8

新しい 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をターゲットにしています。

4

1 に答える 1

4

わかりました!

UIPanGestureRecognizer - 垂直または水平のみの例を使用して、パンを上下に垂直スクロールに制限し、水平にパンすると失敗した状態にしました。

私も使用しました:UIPanGestureRecognizerの動きを制限して、ビューが上下にパンするのをブロックします。

最後に、requiresToFail を次のように逆にしました。

[_slideUpScrollView.panGestureRecognizer requireGestureRecognizerToFail:_panGestureRecognizer];

そして、それはうまくいきます!

質問がある場合や提案する改善点がある場合はお知らせください。

ありがとう!

于 2013-01-26T15:44:56.700 に答える