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) に機能を移動しようとしました。このサブビュー タイルは 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 イベントを受信するようにしたいと述べましたが、このためのコードは含まれていません。これを提示したように、おそらくビューの代わりにレイヤーを使用することを検討する必要があります (タイル固有のイベント処理を行っていない場合)。ここで得たものはすべて、親内のイベント トラッキングで実行できます。ビュー (またはレイヤー) が多すぎると、遅くなることに注意してください。Crosswords で 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 に答える