Реализация перетаскивания UIImageView с использованием UILongPressGestureRecognizer

Я реализую UILongPressGestureRecognizer, который позволит пользователю долго нажимать на ImageView, а затем перетаскивать изображение в другое место. Как только начинается долгое нажатие, я масштабирую вид, чтобы указать, что перетаскивание готово, и пользователь может перетаскивать. Это достигается путем обновления фрейма ImageViews каждый раз, когда селектор вызывается с изменением состояния. Это отлично работает, но я хотел бы создать копию представления и добавить его в родительское представление в начальном состоянии, а затем продолжить обновление кадра копии в родительском представлении. Я хочу сделать это, чтобы устранить любые проблемы с перетаскиванием из прокрутки. Однако я не могу правильно понять логику в методе HandleChangeState. Копия просто не перетаскивается правильно.

Есть идеи?

Часть кода здесь только потому, что я пытаюсь сделать более общий UILongPressGestureRecognizer для UILabel и UIImageView, но это не относится к этой проблеме.

public class LearningViewLongPressGestureRecognizer : UILongPressGestureRecognizer
    {
        private UIImageView draggedImageView;
        private UILabel draggedLabel;
        private RectangleF originalFrame;       
        private UIView parentView;
        private DRAG_CONTENT_TYPE contentType;

        public enum DRAG_CONTENT_TYPE
        {
            UIIMAGEVIEW,
            UILabel
        }

        public static Selector LongPressSelector
        {
            get
            {
                return new Selector ("HandleLongPress");
            }
        }

        public LearningViewLongPressGestureRecognizer (UIView parent, DRAG_CONTENT_TYPE contentType)
        {
            this.contentType = contentType;
            this.AddTarget(this, LongPressSelector);
            this.Delegate = new LongPressRecognizerDelegate();
            this.parentView = parent;
        }

        [Export("HandleLongPress")]
        public void HandleLongPress(UILongPressGestureRecognizer recognizer)
        {
            Console.WriteLine ("HandleLongPress Called.");
            switch (recognizer.State)
            {
            case UIGestureRecognizerState.Began:
                Console.WriteLine ("HandleLongPress Began.");
                HandleBeginState(recognizer);
                break;
            case UIGestureRecognizerState.Changed:
                Console.WriteLine ("HandleLongPress Changed.");
                HandleChangedState(recognizer);
                break;
            case UIGestureRecognizerState.Cancelled:
                Console.WriteLine ("HandleLongPress Canceled.");
                break;
            case UIGestureRecognizerState.Ended:
                Console.WriteLine ("HandleLongPress Ended.");
                break;
            default:
                Console.WriteLine ("HandleLongPress Default.");
                break;
            }
        }

        private void HandleBeginState(UILongPressGestureRecognizer recognizer)
        {
            this.originalFrame = this.View.Frame;                       

            if (contentType == DRAG_CONTENT_TYPE.UIIMAGEVIEW)
            {
                draggedImageView = new UIImageView();
                draggedImageView.Image = ((UIImageView)this.View).Image;    
                draggedImageView.Frame = this.View.Frame;

                //Change the view scale to indicate to the user that the view is selected and ready for dragging.
                draggedImageView.Transform *= CGAffineTransform.MakeScale(1.1f, 1.1f);

                parentView.AddSubview(draggedImageView);
                parentView.BringSubviewToFront(draggedImageView);                   
            }                               
        }

        private void HandleChangedState(UILongPressGestureRecognizer recognizer)
        {           
            PointF currentLocationOfTouchInParentView = recognizer.LocationInView(draggedImageView);//recognizer.TranslationInView(this.View);
            PointF deltaFromOriginal = new PointF(currentLocationOfTouchInParentView.X - originalFrame.X, currentLocationOfTouchInParentView.Y - originalFrame.Y);

            RectangleF newFrame = draggedImageView.Frame;
            newFrame.Offset(deltaFromOriginal.X, deltaFromOriginal.Y);
            draggedImageView.Frame = newFrame;
        }

        private void HandleCanceledState(UILongPressGestureRecognizer recognizer)
        {

        }

        private void HandleEndedState(UILongPressGestureRecognizer recognizer)
        {

        }

        protected class LongPressRecognizerDelegate : UIGestureRecognizerDelegate
        {
            public override bool ShouldReceiveTouch (UIGestureRecognizer recognizer, UITouch touch)
            {
                return true;
            }
        }
    }   

person wheels53    schedule 15.03.2012    source источник


Ответы (1)


Решил мою проблему с расчетами. Мне нужно было взять дельту исходного положения касания, с которого начался жест, и текущего положения касания в родительском представлении, а затем добавить это смещение к перетаскиваемой рамке представления. Ниже мое решение.

private void HandleBeginState(UILongPressGestureRecognizer recognizer)
        {
            this.originalFrame = this.View.Frame;                       
            this.originalTouchLocation = recognizer.LocationInView(parentView);

            if (contentType == DRAG_CONTENT_TYPE.UIIMAGEVIEW)
            {
                draggedImageView = new UIImageView();
                draggedImageView.Image = ((UIImageView)this.View).Image;    
                draggedImageView.Frame = new RectangleF(originalFrame.X, originalFrame.Y, originalFrame.Size.Width, originalFrame.Size.Height);

                parentView.AddSubview(draggedImageView);
                parentView.BringSubviewToFront(draggedImageView);   

                //Change the view scale to indicate to the user that the view is selected and ready for dragging.
                draggedImageView.Transform *= CGAffineTransform.MakeScale(1.1f, 1.1f);
            }                               
        }

        private void HandleChangedState(UILongPressGestureRecognizer recognizer)
        {           
            PointF currentLocationOfTouchInParentView = recognizer.LocationInView(parentView);
            PointF deltaFromOriginalTouch = new PointF(currentLocationOfTouchInParentView.X - originalTouchLocation.X, currentLocationOfTouchInParentView.Y - originalTouchLocation.Y);

            RectangleF newFrame = originalFrame;
            newFrame.Offset(deltaFromOriginalTouch.X, deltaFromOriginalTouch.Y);
            draggedImageView.Frame = newFrame;          
        }
person wheels53    schedule 16.03.2012