使用UILongPressGestureRecognizer实现UIImageView的拖放

时间:2012-03-15 06:06:44

标签: ios drag-and-drop xamarin.ios gestures

我正在实现一个UILongPressGestureRecognizer,它允许用户长按ImageView,然后将图像拖到其他地方。一旦长按开始,我缩放视图以指示拖动已准备好,然后用户可以拖动。这是通过每次使用更改状态调用选择器时更新ImageViews帧来完成的。这完美地工作但我想创建视图的副本并将其添加到开始状态的父视图,然后继续在父视图中更新副本的框架。我想这样做是为了消除从scrollviews拖动的任何问题。我似乎无法在HandleChangeState方法中获得正确的逻辑。副本只是没有正确拖动。

有什么想法吗?

有些代码就在那里,因为我正在尝试为UILabel和UIImageView创建一个更通用的UILongPressGestureRecognizer,但它与此问题无关。

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;
            }
        }
    }   

1 个答案:

答案 0 :(得分:0)

解决了我的计算问题。我需要获取开始手势的原始触摸位置的增量和父视图中的当前触摸位置,然后将该偏移添加到拖动的视图框。以下是我的解决方案。

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;          
        }