親UIView内でのUIViewの移動(UIPanGestureRecognizer)

私はUIViewの内部にあるUIImageViewを移動するために、次のコードを使用しています。

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {

CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                     recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

}

UIViewが親ビューの外に移動しないようにしたいと思います。分時に画像ビューは画面全体に移動できます。

12

8 答え

まず UIImageView の新しいフレームを取得し、 CGRectContainsRect()メソッドを使用してスーパービュー内に完全に入っているかどうかを確認します。もしそうなら、 UImageViewのフレームを新しいフレームに設定します。

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {

    CGPoint translation = [recognizer translationInView:self.view];
    CGRect recognizerFrame = recognizer.view.frame;
    recognizerFrame.origin.x += translation.x;
    recognizerFrame.origin.y += translation.y; 

   //Check if UIImageView is completely inside its superView
    if (CGRectContainsRect(self.view.bounds, recognizerFrame)) {
        recognizer.view.frame = recognizerFrame;
    }
   //Else check if UIImageView is vertically and/or horizontally outside of its
   //superView. If yes, then set UImageView's frame accordingly.
   //This is required so that when user pans rapidly then it provides smooth translation.
    else {
       //Check vertically
        if (recognizerFrame.origin.y < self.view.bounds.origin.y) {
            recognizerFrame.origin.y = 0;
        }        
        else if (recognizerFrame.origin.y + recognizerFrame.size.height > self.view.bounds.size.height) {
            recognizerFrame.origin.y = self.view.bounds.size.height - recognizerFrame.size.height;
        }

       //Check horizantally
        if (recognizerFrame.origin.x < self.view.bounds.origin.x) {
            recognizerFrame.origin.x = 0;
        }
        else if (recognizerFrame.origin.x + recognizerFrame.size.width > self.view.bounds.size.width) {
            recognizerFrame.origin.x = self.view.bounds.size.width - recognizerFrame.size.width;
        }
    }

   //Reset translation so that on next pan recognition
   //we get correct translation value
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}

両方の CGRects が同じ座標系になるように UIImageViewboundsframe を渡すようにしてください。

11
追加された
@micantox私はいくつかのポイントに同意し、私の答えを更新しました。私はselfViewが自分のコードでsuperViewとしてself.viewを使っていたので、superViewについてはselfViewがimageViewのsuperViewであることを知っています。
追加された 著者 Geek,
@IconicDigitalすべての場合に正しい翻訳効果を得るために私の更新された答えを見てください。
追加された 著者 Geek,
@ReidBelton recognizer.view.frame を使用するのは間違いありません。それが動かなかった理由は、「あなたはその価値を全く変えていない」または「あなたがドラッグしたいもの以外の視界を変えていた」ことができます。
追加された 著者 Geek,
私は何が欠けているのかは分かりませんが、UIPanGestureRecognizerは私が座っている場所から "フレーム"プロパティを持っていないので、recognizer.frameは機能しません。私はrecognizer.view.frameを使用することができましたが、recognizer.view.frameをrecognizerFrameに設定すると、一見同じ値を自分自身に割り当てるため、何もしません。私は以下のような別の方法を試してみましたが、これは私のためにはうまくいきましたが、まだまだ興味があります。誰かが助言できるなら、私はそれを感謝します、ありがとう。
追加された 著者 Reid Belton,
それ以外のすべては素晴らしく、良いことです:あなたはrecognizer.viewのsuperviewがself.viewであることを知らず、ユーザーがsuperviewの境界の外で本当に素早くパンすると、認識器のフレームが真ん中で凍っているという醜い効果が得られますスーパービューの境界の最後に、このユーザーがパンニングを続けると、ビューはユーザーの指の下にはなく、パンニングを続けます。全体的に、あなたはより良くすることができます。
追加された 著者 micantox,

試してみてください:

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer 
{
    if (gesture.state==UIGestureRecognizerStateChanged || gesture.state == UIGestureRecognizerStateEnded){
        UIView *superview = recognizer.view.superview;
        CGSize superviewSize = superview.bounds.size;
        CGSize thisSize = recognizer.view.size;
        CGPoint translation = [recognizer translationInView:self.view];
        CGPoint center = CGPointMake(recognizer.view.center.x + translation.x,
                                 recognizer.view.center.y + translation.y);

        CGPoint resetTranslation = CGPointMake(translation.x, translation.y);

        if(center.x - thisSize.width/2 < 0)
            center.x = thisSize.width/2;
        else if (center.x + thisSize.width/2 > superviewSize.width)
            center.x = superviewSize.width-thisSize.width/2;
        else
            resetTranslation.x = 0; //Only reset the horizontal translation if the view *did* translate horizontally

        if(center.y - thisSize.height/2 < 0)
            center.y = thisSize.height/2;
        else if(center.y + thisSize.height/2 > superviewSize.height)
            center.y = superviewSize.height-thisSize.height/2;
        else
            resetTranslation.y = 0; //Only reset the vertical translation if the view *did* translate vertically

        recognizer.view.center = center;
        [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    }
}

この方法で親ビューの範囲外に移動することはありませんし、範囲外に移動しようとするとエッジに「スティック」するだけです!

8
追加された
魅力のように動作します!ありがとうございました
追加された 著者 MBH,

試してみてください:

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer 
{
    if (gesture.state==UIGestureRecognizerStateChanged || gesture.state == UIGestureRecognizerStateEnded){
        UIView *superview = recognizer.view.superview;
        CGSize superviewSize = superview.bounds.size;
        CGSize thisSize = recognizer.view.size;
        CGPoint translation = [recognizer translationInView:self.view];
        CGPoint center = CGPointMake(recognizer.view.center.x + translation.x,
                                 recognizer.view.center.y + translation.y);

        CGPoint resetTranslation = CGPointMake(translation.x, translation.y);

        if(center.x - thisSize.width/2 < 0)
            center.x = thisSize.width/2;
        else if (center.x + thisSize.width/2 > superviewSize.width)
            center.x = superviewSize.width-thisSize.width/2;
        else
            resetTranslation.x = 0; //Only reset the horizontal translation if the view *did* translate horizontally

        if(center.y - thisSize.height/2 < 0)
            center.y = thisSize.height/2;
        else if(center.y + thisSize.height/2 > superviewSize.height)
            center.y = superviewSize.height-thisSize.height/2;
        else
            resetTranslation.y = 0; //Only reset the vertical translation if the view *did* translate vertically

        recognizer.view.center = center;
        [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    }
}

この方法で親ビューの範囲外に移動することはありませんし、範囲外に移動しようとするとエッジに「スティック」するだけです!

8
追加された
魅力のように動作します!ありがとうございました
追加された 著者 MBH,

その frame が親ビューの bounds 内にある場合にのみ、 recognizer.view.center を新しい値に設定する必要があります。それらが含まれていることを確認するには、 recognizer.view.superview.bounds および recognizer.view.frameCGRectContainsRect を使用します。

ビューの中心点が親の境界外になるまで、親ビューの外側に画像ビューを移動させたい場合は、 UIViewconvertPoint:toView メソッドを使用できます。 >新しい CGPoint が親の範囲外にないことを確認します。

1
追加された

その frame が親ビューの bounds 内にある場合にのみ、 recognizer.view.center を新しい値に設定する必要があります。それらが含まれていることを確認するには、 recognizer.view.superview.bounds および recognizer.view.frameCGRectContainsRect を使用します。

ビューの中心点が親の境界外になるまで、親ビューの外側に画像ビューを移動させたい場合は、 UIViewconvertPoint:toView メソッドを使用できます。 >新しい CGPoint が親の範囲外にないことを確認します。

1
追加された

スイムアップ版のマイサックス解答

let gesture = UIPanGestureRecognizer(target: self, action: #selector(self.wasDragged(gestureRecognizer:)))
imageView.addGestureRecognizer(gesture)
imageView.isUserInteractionEnabled = true

@objc func wasDragged(gestureRecognizer: UIPanGestureRecognizer) {
if gestureRecognizer.state == UIGestureRecognizerState.changed || gestureRecognizer.state == UIGestureRecognizerState.ended {
   let superview = gestureRecognizer.view?.superview
   let superviewSize = superview?.bounds.size
   let thisSize = gestureRecognizer.view?.frame.size
   let translation = gestureRecognizer.translation(in: self.view)
   var center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
   var resetTranslation = CGPoint(x: translation.x, y: translation.y)

   if center.x - (thisSize?.width)!/2 < 0 {
       center.x = (thisSize?.width)!/2
       } else if center.x + (thisSize?.width)!/2 > (superviewSize?.width)! {
       center.x = (superviewSize?.width)!-(thisSize?.width)!/2
       } else {
         resetTranslation.x = 0 //Only reset the horizontal translation if the view *did* translate horizontally
       }

   if center.y - (thisSize?.height)!/2 < 0 {
       center.y = (thisSize?.height)!/2
      } else if center.y + (thisSize?.height)!/2 > (superviewSize?.height)! {
       center.y = (superviewSize?.height)!-(thisSize?.height)!/2
      } else {
        resetTranslation.y = 0 //Only reset the vertical translation if the view *did* translate vertically
      }

      gestureRecognizer.view?.center = center
      gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
    } 
}
0
追加された
if (gesture.state==UIGestureRecognizerStateChanged){

CGPoint translation = [recognizer translationInView:self.view];

CGRect rectToCheck=CGRectMake(yourView.frame.origin.x+translation.x,       yourView.frame.origin.y+translation.y, CGRectGetWidth(yourView.frame),     CGRectGetHeight(yourView.frame));

     if(CGRectContainsRect(self.view.bounds,rectToCheck))// check that the rect that is   going to form lies within the bounds of self.view
     {

     yourView.frame=CGRectMake(yourView.frame.origin.x+translation.x,  yourView.frame.origin.y+translation.y, CGRectGetWidth(yourView.frame),  CGRectGetHeight(yourView.frame)); 
     }
     [gesture setTranslation:CGPointZero yourView];//important to set this 

 }

P.S.ジェスチャの状態ブロックを使用して、開始、移動、削除します。すなわちUIGestureRecognizerStateBegan UIGestureRecognizerStateChanged UIGestureRecognizerStateEnded

0
追加された
if (gesture.state==UIGestureRecognizerStateChanged){

CGPoint translation = [recognizer translationInView:self.view];

CGRect rectToCheck=CGRectMake(yourView.frame.origin.x+translation.x,       yourView.frame.origin.y+translation.y, CGRectGetWidth(yourView.frame),     CGRectGetHeight(yourView.frame));

     if(CGRectContainsRect(self.view.bounds,rectToCheck))// check that the rect that is   going to form lies within the bounds of self.view
     {

     yourView.frame=CGRectMake(yourView.frame.origin.x+translation.x,  yourView.frame.origin.y+translation.y, CGRectGetWidth(yourView.frame),  CGRectGetHeight(yourView.frame)); 
     }
     [gesture setTranslation:CGPointZero yourView];//important to set this 

 }

P.S.ジェスチャの状態ブロックを使用して、開始、移動、削除します。すなわちUIGestureRecognizerStateBegan UIGestureRecognizerStateChanged UIGestureRecognizerStateEnded

0
追加された