I have a custom UIView that generates a set of subviews and display them in rows and columns like tiles. What I am trying to achieve is to allow the user to touch the screen and as the finger move, the tiles beneath it disappears.
The code below is the custom UIView that contains the tiles:
- (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];
}
This approach works but however if the tiles get denser (i.e. small tiles and more tiles on the screen). The iPhone is less responsive as the finger move. It may be the hitTest taking a toll on the processor as it struggles to keep up but would like some opinions.
My questions are:
Is this an efficient way / right way to implement the touchesMoved?
If it isn't, what would be the recommended approach?
I tried moving the functionality into a custom Tile class (a sub UIView) which the class above would create and add as a subview. This subview Tile can handle the TouchesBegan but as the finger move, the other tiles does not receive the TouchesBegan even since the touches are still part of the initial touch sequence. Is there a way to implement it through the subview Tile class, how do other tiles receive the TouchesBegan/TouchesMoved event as the finger move?
//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;
}
}
(Not sure why the numbering restarted with 1 here...)
one addition, instead of hit testing, you can just check if the point lies in the CGRect that represents the frame of each subview. I have a similar app, and this worked best for me.
for (UIView* aSubview in self.subviews) {
if([aSubview pointInside: [self convertPoint:touchPoint toView:aSubview] withEvent:event]){
//Do stuff
}
}
Just an idea that may help... I have not tested this, but, after detecting the tap on a particular imageview turn off userInteractionEnabled of the all other imageviews...
I suppose this will help increase a little bit the speed, as iPhone will not last resources trying to find which image is being tapped during a drag. The same is true for multitouch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With