没有调用touchesMoved的UIScrollView

时间:2012-09-04 07:52:09

标签: objective-c ios uiscrollview zooming panning

我有一个包含UIImageView的UIScrollView。 UIScrollView允许通过UIImageView进行缩放和平移。

问题是我每次都想知道手指的动作,而我正试图用touchesMoved方法捕捉事件。 但它并没有起作用,尽管触摸了正确的触摸和触摸,并且正确调用了它们。

实际上,如果手指移动非常小,则会调用touchesMoved,并且UIScrollView不会开始平移。在UIScrollView开始移动的那一刻,事件停止被调用。

有人知道问题是什么以及如何解决? 我认为可能内部的UIImageView正在捕捉事件或类似事件。

5 个答案:

答案 0 :(得分:1)

实际上,这确实是个问题,因为 UIScrollView TouchesMoved 事件(即使传播了几个第一个)。

所以,我刚刚提出了直接从UIWindow 获取事件的方法。这肯定不是应用程序结构意义上的最佳方法,但在某些自定义情况下(这正是我需要的)很好。

(示例在 MonoTouch C#中)。

创建自定义UIWindow (我没有在这里展示如何使用我的自定义逻辑(使用MvvmCross框架)将标准UIWindow替换为MyWindow,但这很简单,通常在appDelegate初始化逻辑中完成 - 你会发现在google / stack overflow中:

public class MyWindow : UIWindow
{
    public MyWindow(RectangleF bounds) : base(bounds)
    {

    }

    public override void SendEvent(UIEvent evt)
    {
        if (evt.Type == UIEventType.Touches) {
            var el = (UITouch)evt.AllTouches.AnyObject;

            if (el.Phase == UITouchPhase.Began)
            {
                if(OnTouchBegan != null)
                    OnTouchBegan(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

            if (el.Phase == UITouchPhase.Moved)
            {
                if(OnTouchMoved != null)
                    OnTouchMoved(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

            if (el.Phase == UITouchPhase.Ended)
            {
                if(OnTouchEnd != null)
                    OnTouchEnd(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

            if (el.Phase == UITouchPhase.Cancelled)
            {
                if(OnTouchCancel != null)
                    OnTouchCancel(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

        } else
            MvxTrace.Trace (evt.Type == null ?  "-" : evt.ToString ());
        base.SendEvent(evt);
    }

    public event TouchCommand OnTouchBegan;
    public event TouchCommand OnTouchEnd;
    public event TouchCommand OnTouchCancel;
    public event TouchCommand OnTouchMoved;

}

public class TouchCommandArgs : EventArgs
{
    public NSSet Touches { get; set; }
    public UIEvent Evt { get; set; }

    public TouchCommandArgs(NSSet touches, UIEvent evt)
    {
        Touches = touches;
        Evt = evt;
    }
}

并在处理事件的地方订阅自定义事件处理程序

var window = (MyWindow) UIApplication.SharedApplication.KeyWindow;
window.OnTouchBegan += view_OnTouchBegan;
window.OnTouchMoved += view_OnTouchMoved;
window.OnTouchCancel += view_OnTouchCancel;
window.OnTouchEnd += view_OnTouchEnd;

处理程序(这些都是你自己的):

void view_OnTouchBegan(object sender, TouchCommandArgs args)
{
    // do your logic
}

在这种情况下,事件将同时处理(在两个地方:你的和UIScrollView),所以另外如果你想要,你可以取消窗口的事件传播只有你想要阻止任何其他处理程序除了你的(你)例如,可以为处理程序添加“Handled”标志。

答案 1 :(得分:0)

创建 UIScrollView 类的子类并覆盖 touchesBegan:以及其他触摸方法,如下所示:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // If not dragging, send event to next responder
    if (!self.dragging)
    { 
        [self.nextResponder touchesBegan: touches withEvent:event]; 
    }
    else
    {
        [super touchesEnded: touches withEvent: event];
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // If not dragging, send event to next responder
    if(!self.dragging)
    { 
        [self.nextResponder touchesBegan: touches withEvent:event]; 
    }
    else
    {
        [super touchesEnded: touches withEvent: event];
    }
 }

 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // If not dragging, send event to next responder
    if (!self.dragging)
    { 
        [self.nextResponder touchesBegan: touches withEvent:event]; 
    }
    else
    {
        [super touchesEnded: touches withEvent: event];
    }
}

答案 2 :(得分:0)

scrollview属性canCancelContentTouches = NO允许触摸事件在响应者链中向上传递。

答案 3 :(得分:0)

尝试使用UIScrollViewDelegate跟踪偏移量变化或缩放比例变化。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewDidZoom:(UIScrollView *)scrollView;

或检查zoomScale之间的UIScrollView值变化{/ 1}}。

答案 4 :(得分:0)

请选中此项以使用滚动视图的平移手势识别触摸事件(开始,移动,结束)

Class CustomScrollView:UIScrollView
{

CustomScrollView()
{

 (this.GestureRecognizers[1] as UIPanGestureRecognizer).AddTarget(() => this.PanHandle(this.GestureRecognizers[1] as UIPanGestureRecognizer));
    

}


 private void PanHandle(UIPanGestureRecognizer gestureRecognizer)
          
  {
  var touchLocation=gestureRecognizer.LocationInView(this)
    
       

  if (gestureRecognizer.State == UIGestureRecognizerState.Began)
            
    {
             
      //Touches began
             
   }
     
else if (gestureRecognizer.State == UIGestureRecognizerState.Changed)
            
   {
           
        //Touches Moved
             
   }
               
 else if (gestureRecognizer.State == UIGestureRecognizerState.Ended)
         
       {
             
       //Touches ended
              
  }
           
 }

    }

Regards,
Ashwin