代码之家  ›  专栏  ›  技术社区  ›  Ronnie Liew

实现TouchsMoved的正确方法?

  •  5
  • Ronnie Liew  · 技术社区  · 17 年前

    我有一个自定义的uiview,它生成一组子视图,并将它们显示在像tiles一样的行和列中。我正在尝试实现的是允许用户触摸屏幕,当手指移动时,屏幕下面的瓷砖就消失了。

    下面的代码是包含图块的自定义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的响应能力降低。这可能是对处理器的冲击测试,因为它很难跟上,但需要一些意见。

    我的问题是:

    1. 这是实施触摸移动的有效方法/正确方法吗?

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

    3. 我尝试将该功能移动到自定义平铺类(子uiview)中,上面的类将创建该类并将其添加为子视图。这个子视图图块可以处理touchesbegan,但是当手指移动时,其他图块不会接收touchesbegan,即使接触仍然是初始触摸序列的一部分。是否有方法通过SubView Tile类实现它,其他Tile如何在手指移动时接收TouchsBegan/TouchsMoved事件?

    3 回复  |  直到 17 年前
        1
  •  11
  •   Ben Gottlieb    17 年前
    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. 你需要更清楚地决定在你的父母身上应该发生什么,以及在每个瓷砖上应该发生什么。您在上面提到您希望Tiles接收ToucheSbegan事件,但是您没有为此包含任何代码。在您介绍这一点时,您可能应该考虑使用层而不是视图(如果您没有执行任何特定于图块的事件处理)。您在这里所得到的一切都可以通过父级中的事件跟踪来完成。记住,如果你有太多的视图(或图层),它会变慢。我们在纵横填字游戏中尝试了15x15的网格,虽然对某些事情来说还可以,但最终我们放弃了使用网格层的方法。

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

        2
  •  5
  •   Corey Floyd    17 年前

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

    for (UIView* aSubview in self.subviews) {
    
        if([aSubview pointInside: [self convertPoint:touchPoint toView:aSubview] withEvent:event]){
    
           //Do stuff
        }
    }
    
        3
  •  1
  •   Duck    17 年前

    只是一个有助于…我没有测试过这个,但是,在检测到特定ImageView上的点击之后,关闭所有其他ImageView的用户交互启用…

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