5

我有一个自定义 UIView 生成一组子视图并将它们显示在行和列中,如瓷砖。我想要实现的是允许用户触摸屏幕,当手指移动时,它下面的图块就会消失。

下面的代码是包含磁贴的自定义 UIView:

- (id)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {
        int i, j;
        int maxCol = floor(self.frame.size.width/TILE_SPACING);
        int maxRow = floor(self.frame.size.height/TILE_SPACING);

        CGRect frame = CGRectMake(0, 0, TILE_WIDTH, TILE_HEIGHT);
        UIView *tile;       

        for (i = 0; i<maxCol; i++) {
            for (j = 0; j < maxRow; j++) {
                frame.origin.x =  i * (TILE_SPACING) + TILE_PADDING;
                frame.origin.y =  j * (TILE_SPACING) + TILE_PADDING;
                tile = [[UIView alloc] initWithFrame:frame];

                [self addSubview:tile];
                [tile release]; 
            }
        }

    }
    return self;
}


- (void)touchesBegan: (NSSet *)touches withEvent:(UIEvent *)event {
    UIView *tile = [self hitTest:[[touches anyObject] locationInView:self] withEvent:nil];

    if (tile != self)
        [tile setHidden:YES];
}



- (void)touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
    UIView *tile = [self hitTest:[[touches anyObject] locationInView:self] withEvent:nil];

    if (tile != self)
        [tile setHidden:YES];
}

这种方法有效,但是如果图块变得更密集(即屏幕上的小图块和更多图块)。手指移动时,iPhone 的响应速度较慢。可能是 hitTest 对处理器造成了影响,因为它难以跟上,但希望得到一些意见。

我的问题是:

  1. 这是实现 touchesMoved 的有效方式/正确方式吗?

  2. 如果不是,推荐的方法是什么?

  3. 我尝试将功能移动到自定义 Tile 类(子 UIView)中,上面的类将创建并添加为子视图。此子视图 Tile 可以处理 TouchesBegan,但随着手指移动,即使触摸仍然是初始触摸序列的一部分,其他图块也不会收到 TouchesBegan。有没有办法通过子视图Tile类来实现,其他瓦片如何在手指移动时接收到TouchesBegan/TouchesMoved事件?

4

3 回答 3

11
  1. 不是真的,根据我的经验。
  2. 从您设置视图的方式来看,似乎有一种更有效的方法来确定哪个被窃听:

 //In your init method, make sure each tile doesn't respond to clicks on its own
 ...
 tile.userInteractionEnabled = NO;
 ...


 - (void) touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
      CGPoint tappedPt = [[touches anyObject] locationInView: self];
      int     xPos = tappedPt.x / (TILE_SPACING + TILE_PADDING);
      int     yPos = tappedPt.y / (TILE_SPACING + TILE_PADDING);
      int     tilesAcross = (self.bounds.size.width / (TILE_SPACING + TILE_PADDING));
      int     index = xPos + yPos * tilesAcross;

      if (index < self.subviews.count) {
          UIView  *tappedTile = [self.subviews objectAtIndex: index];
          tappedTile.hidden = YES;
      }
  }

  1. 您需要更清楚地决定在您的父级中应该发生什么,以及在每个图块中应该发生什么。您在上面提到您希望磁贴接收 touchesBegan 事件,但您没有为此包含任何代码。当您介绍此内容时,您可能应该考虑使用图层而不是视图(如果您不进行任何特定于图块的事件处理)。您在这里所拥有的一切都可以通过父级中的事件跟踪来完成。请记住,如果您有太多视图(或层),它会变慢。我们在填字游戏中尝试了 15x15 的网格,虽然在某些情况下还可以,但最终我们放弃了分层网格的方法。

(不知道为什么编号在这里以 1 重新开始......)

于 2008-10-18T20:21:13.753 回答
5

另外,您可以检查点是否位于代表每个子视图的框架的 CGRect 中,而不是命中测试。我有一个类似的应用程序,这对我来说效果最好。

for (UIView* aSubview in self.subviews) {

    if([aSubview pointInside: [self convertPoint:touchPoint toView:aSubview] withEvent:event]){

       //Do stuff
    }
}
于 2009-01-23T06:39:48.717 回答
1

只是一个可能有帮助的想法......我没有对此进行测试,但是,在检测到特定图像视图上的点击后,关闭所有其他图像视图的 userInteractionEnabled ......

我想这将有助于提高一点速度,因为 iPhone 不会持续资源试图找到在拖动过程中被点击的图像。多点触控也是如此。

于 2008-12-30T22:27:23.887 回答