Iphone “我怎么能?”;捕获;在iOS设备上进行滑动手势时的子视图?

Iphone “我怎么能?”;捕获;在iOS设备上进行滑动手势时的子视图?,iphone,ipad,ios,uikit,Iphone,Ipad,Ios,Uikit,我正在构建一个iOS棋盘游戏(类似于拼字游戏或文字游戏),它涉及到在屏幕上移动小瓷砖,我发现用户有时很难触摸和移动瓷砖,因为它们太小了。由于游戏的设计,我不能增加瓷砖的大小,所以我不得不实施一些小技巧,让用户更容易触摸和移动瓷砖,而且效果很好。剩下的唯一问题是,用户有时几乎不接触互动程序的外部,当用户尝试移动互动程序时,互动程序会停留在原来的位置 我有两个办法来解决这个问题 如果用户触摸屏幕时未触摸互动程序,我可以使用父视图的触摸位置查找距离触摸位置最近的互动程序,并以某种方式将触摸事件转发到该

我正在构建一个iOS棋盘游戏(类似于拼字游戏或文字游戏),它涉及到在屏幕上移动小瓷砖,我发现用户有时很难触摸和移动瓷砖,因为它们太小了。由于游戏的设计,我不能增加瓷砖的大小,所以我不得不实施一些小技巧,让用户更容易触摸和移动瓷砖,而且效果很好。剩下的唯一问题是,用户有时几乎不接触互动程序的外部,当用户尝试移动互动程序时,互动程序会停留在原来的位置

我有两个办法来解决这个问题

  • 如果用户触摸屏幕时未触摸互动程序,我可以使用父视图的触摸位置查找距离触摸位置最近的互动程序,并以某种方式将触摸事件转发到该互动程序的视图
  • 如果用户触摸屏幕时没有触摸到某个磁贴,那么当用户试图移动它时将手指拖过它时,我可以以某种方式“捕捉”该磁贴
  • 我更愿意实施解决方案2,因为解决方案1有太多与之相关的问题,更不用说解决方案2是一种更现实的体验。也就是说,当用户将手指拖动到瓷砖上并发送触摸事件以将其移动到手指所在的位置时,我如何“捕捉”瓷砖

    目前,my tiles是作为UIView的子类实现的,它们直接处理触摸事件(touchesBegain、touchesMoved和touchesEnded)。因此,如果用户仅在视图外触摸,并将手指拖到视图上,则不会收到任何触摸事件,因为它没有收到初始的ToucheSBegind事件

    提前感谢你的智慧

    也许您应该让“board”视图处理所有拖动操作。当触摸开始时,在该点上有一个平铺,然后开始拖动它。否则,请在触摸移动时进行检查,并在找到平铺后立即开始拖动它

    您可以在board视图中覆盖
    hitTest:withEvent:
    ,这样它仍然可以检测触摸何时碰到磁贴,但始终会返回自身,以便触摸事件进入board视图(例如,在单独的成员变量中记录被击中的子视图,以便您知道在触摸事件开始进入时开始拖动什么)

    更多详细信息

    处理触摸时,UIView将使用hitTest查找应接收触摸事件的视图。默认实现会检查每个子视图,以便层次结构中“最深”的子视图能够接触到。为了使board视图接收触摸,您必须在所有平铺视图上禁用userInteraction。但这意味着您无法使用hitTest查找被触摸的互动程序,因为它会忽略禁用了userInteraction的视图

    所以我要说的是在触摸视图上启用用户交互。但是覆盖board视图上的hitTest,以便它首先调用超级实现以查找一个磁贴(如果结果是
    self
    ,则board本身被击中)。无需实现自己的磁贴搜索。大概是这样的:

    - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
    {
      UIView *hitView = [super hitTest:point withEvent:event];
      if ( hitView != self )
        self.draggingTile = hitView;
      return self;
    }
    
    现在您知道要在
    touchsmoved
    中移动哪些磁贴了。但是,我认为在触摸移动时不会调用hitTest,因此如果尚未拾取磁贴,则您可能必须手动调用它(您可以从传递到触摸移动的触摸中获取
    点和
    事件
    ,也许您应该拥有“board”视图处理所有拖动操作。当触摸开始时,在该点上有一个互动程序,然后开始拖动它。否则,请在触摸移动时进行检查,一旦找到互动程序,就开始拖动它

    您可以在board视图中覆盖
    hitTest:withEvent:
    ,这样它仍然可以检测触摸何时碰到磁贴,但始终会返回自身,以便触摸事件进入board视图(例如,在单独的成员变量中记录被击中的子视图,以便您知道在触摸事件开始进入时开始拖动什么)

    更多详细信息

    处理触摸时,UIView将使用hitTest查找应接收触摸事件的视图。默认实现检查每个子视图,以便层次结构中的子视图获取触摸。为了使board视图接收触摸,您必须在所有磁贴视图上禁用userInteraction。但这意味着您无法使用hitTest查找被触摸的磁贴,因为它会忽略禁用userInteraction的视图

    因此,我要说的是在触摸视图上保持启用userInteraction。但是在board视图上覆盖hitTest,以便它首先调用超级实现以查找磁贴(如果结果是
    self
    ,则磁贴本身被击中)。无需实现您自己的磁贴搜索。类似于以下内容:

    - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
    {
      UIView *hitView = [super hitTest:point withEvent:event];
      if ( hitView != self )
        self.draggingTile = hitView;
      return self;
    }
    
    现在您知道了在触摸中移动哪个磁贴了。但是,我认为在触摸移动时不会调用hitTest,因此如果尚未拾取磁贴,您可能需要手动调用它(您可以从传递到触摸移动的触摸中获得
    事件
    。您查看了吗?我认为您最好的选择是在电路板的视图中添加一个UIPanGestureRecognizer识别器,然后将选择器返回到UIViewController

    ViewDidLoad中的设置:

    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]
                                                          initWithTarget:self action:@selector(handlePan:)];
    
    [[self view] addGestureRecognizer:panGestureRecognizer];
    
    然后实现了选择器:

        - (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer{
              CGPoint currentPoint = [gesture locationInView:[self view]];
        }
    
    设置手势识别器时,可以设置参数以限制回调(只能用一个手指识别平移,等等。在回调中,您可以检查手势属性,查看平移是否继续或是否即将结束。您还可以抓住当前点,确定它是否在平铺中或附近。

    您查看了吗?我想您最好的选择是在你董事会的观点是什么