2

誰もがカメラのロック画面でドラッグ可能なビューを知っています

ここに画像の説明を入力してください

似たようなものが欲しいです。私のレイアウトは次のようになります

ここに画像の説明を入力してください

  • このサブビューは下からドラッグ可能で、セトレインの高さで開いたままにする必要があります。
  • また、高速で上にスワイプすると、サブビューを上にドラッグすると自動的に開きますが、最大位置の前で停止します。上にスライドしてから下にスライドすると、下にスライドする必要があります。
  • それも自然に下がるでしょう
  • タップすると、それ自体が上下にスライドするはずです

この動作は、ロック画面でかなりよくわかります(高さの停止を除く)。最大値を設定するなど、さまざまなことを試しUIPanGestureRecognizerましたが、スライドできません。

UIKitにあらかじめパッケージ化されているものがありますか、それとも自分でやらなければなりませんか。そうでない場合、この動作の良いアプローチは何でしょうか?

4

1 に答える 1

6

計画は次のとおりです。UIViewをサブクラス化します。いくつかのプロパティを追加し、いくつかのメソッドをオーバーライドします。アイデアは、touchesBeganとtouchsMovedで指に動きを指示させることです。指がtouchsEndedで持ち上げられると、ビューを適切な静止位置にアニメートします。私が提供しているコードサンプルでは、​​これは完全に拡張または完全に収縮されますが、必要に応じていつでも収縮させることができます。

少し慣性を適用したいようです。自分でアニメーションを追加する必要があるため、これは少し複雑ですが、ここでも、正しいアニメーションをプラグインする必要があります(たとえば、タイミング関数を使用して、終了点を超えてアニメーション化してから元に戻す)。ユーザーが移動を終了した後に起動します。ファンシーになりたい場合は、スワイプの速度を追跡し、この速度/勢いに基づいてアニメーションを起動します。

以下は、引き出しを出し入れするのに役立つコードサンプルです。それはあなたが説明した空想を持っていませんが、それはあなたにその種の行動をどのようにそしてどこに導入するかを理解するための基礎を与えるはずです。

クラスにはいくつかのプロパティ/アイバーが必要です。「現在のポイント」、原点、天井(ビューが上にドラッグするのをやめるポイント、または「アウト」にあるポイント、および床(最大yオフセット) 、またはそれが下に行かない座標)。

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint startPt = [touch locationInView:self];
    self.currentPoint = startPt;

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    CGPoint activePoint = [[touches anyObject] locationInView:self];

    //new position
    CGPoint newPoint = CGPointMake(self.center.x,
                                   self.center.y + (activePoint.y - currentPoint.y));

    if (newPoint.y > self.draggingFloor) {
        //too low
        newPoint.y = self.draggingFloor;

    } else if (newPoint.y < self.draggingCeiling) {
        //too high
        newPoint.y = self.draggingCeiling;
    }

    self.center = newPoint;

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    //The user isn't touching. Now we can adjust to drawer to a "better" position.
    //The 150f here is going to depend on how far the view should be dragged before it opens.
    CGFloat median = pullDrawerYOrigin + 150.0f;
    CGFloat position = self.center.y;

    if (position <= median) {
        //We're closer to open than closed. So open all the way. 
        [self animateDrawerToPositionYesForOpen:YES];
    }

    else if (position >= median)  {
        //close
        [self animateDrawerToPositionYesForOpen:NO];
    }


}

- (CGFloat) draggingFloor {

    //Don't drag any lower than this.
    if (!__draggingFloor) {
        __draggingFloor = pullDrawerYOrigin + (self.bounds.size.height *.5);
    }

    return __draggingFloor;
}

- (CGFloat) draggingCeiling {

    //Don't drag any higher than this.
    if (!__draggingCeiling) {
        __draggingCeiling = self.superview.bounds.size.height + (self.bounds.size.height * .05);
    }

    return __draggingCeiling;

}
- (void) animateDrawerToPositionYesForOpen:(BOOL)position {

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    [UIView setAnimationDuration:.2];

    CGPoint myCenter = self.center;

    if (position == YES) {
        myCenter.y = self.draggingCeiling;
    }

    else if (position == NO) {
        myCenter.y = self.draggingFloor;
    }

    self.center = myCenter;

    [UIView commitAnimations];

}
于 2012-07-03T00:23:28.800 に答える