Swipe to Reveal Menu like Tweetie
I've been working on a new app and was really hoping to implement a swipe to reveal more options menu inside my application. I've searched and searched, but it seems no one else has successfully made it work (aside from Loren). What I'm trying to do is swipe the cell, and simultaneously use CABasicAnimation to push it to x: 320, and add a subview below this that would have the buttons etc.. I'm using willBeginEditing to detect the swipe to avoid subclassing. Here's the code:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
theAnimation.duration=0.0;
theAnimation.repeatCount=0;
theAnimation.autoreverses=NO;
theAnimation.removedOnCompletion = NO;
theAnimation.fillMode = kCAFillModeForwards;
theAnimation.fromValue=[NSNumber numberWithFloat:0];
theAnimation.toValue=[NSNumber numberWithFloat:+320];
[cell.layer addAnimation:theAnimation forKey:@"animateLayer"];
CGRect frame = CGRectMake(0, 59 * indexPath.row, 320, 59);
UIView *menu =开发者_C百科 [[[UIView alloc] initWithFrame:frame] autorelease];
NSString *path = [NSString stringWithFormat:@"%@%@",
[[NSBundle mainBundle] resourcePath],
@"/flick.wav"];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
self.menu.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"dots.png"]];
[self.view addSubview:menu];
[self.view sendSubviewToBack:menu];
}
- (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context
{
// Release
[self release];
}
#pragma mark - Swipe Menu II
- (void)scrollViewDidScroll:(UIScrollView *)tableView {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:nil];
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
theAnimation.duration=0.2;
theAnimation.repeatCount=0;
theAnimation.autoreverses=NO;
theAnimation.fromValue=[NSNumber numberWithFloat:320];
theAnimation.toValue=[NSNumber numberWithFloat:0]
;
[cell.layer addAnimation:theAnimation forKey:@"animateLayer"];
}
The problem is the sliding back of the cell - I want to do it when any touch outside the menu view is received, but because it is a scrollView, I can't. The ScrollViewdidScroll Method only animates the cell back to its normal place once it is scrolled of the viewport. (As in, under the NavigationBar or object that obscures it) The last key issue is the ability to detect if a menu is already visible or active and a cell is already off of the screen, slide the cell back to its original position, remove the menu view, and then slide the other cell out and add the menu.
I would like to be the first beside Loren to implement this as so many others have tried, especially on StackOverflow.
I apologize for the poor formatting in the code.
Thanks in advance, Kolin
I've actually made this work quite nicely, you can check out the project here: http://www.thermoglobalnuclearwar.com/opensource/
It also overcomes the problem in Tweetie where you cannot swipe the same cell twice without first swiping something else.
If you make any constructive changes, or need any help, let me know!
Loren's implementation has a fatal flaw, which is if you swipe on a cell, then scroll the table, you cannot re-swipe the same cell until you swipe a different cell. I believe this is because the tableview believes the cell is still being edited until you try and "edit" another cell.
You may want to investigate doing something else instead, like using a UISwipeGestureRecognizer attached to the cell to detect the swipe.
I can think of 2 approaches to try and detect taps outside of the cell as well. The first is to subclass UIApplication and override -sendEvent:
. You can use this to detect the tap event and dismiss the cell "editing". The main problem here is giving the UIApplication subclass knowledge about your cell. The second approach is to slap a custom UIView subclass over the entire screen and in -hitTest:withEvent:
you can test to see if the touch belongs to the area over your cell. If it doesn't, dismiss the cell "editing". In both cases, return nil to allow the event to proceed to the underlying views (and don't forget to remove this overlay view after the event happens). You may also want to test the UIEvent to make sure it contains a new touch before dismissing the cell.
精彩评论