views:

2172

answers:

3

How can I implement tweetie like swipe menu?

I'm done with developing a tableviewcontroller with a customcell. The customcell implements touchesbegan and touchesMoved. It also reports swipe gestures via a selector to the parent tableviewcontroller.

Now how should I go about hiding the "Swiped" cell and replacing it with a "swipe menu view" and how should I get the actions from the buttons present on the swipeview?

+8  A: 

Each table view cell has a contentView that encompasses the whole area of the cell. Add your swipe-menu view as a single container view with an opaque background to the contentview so it's on top of everything else. Position it so it's flush left (x=0), set the width to 0, and set it as hidden. That single container can include any other subview (buttons, etc) and you can set the cell view itself as the target of the button events (then bubble it up to the parent table view along with cell index information).

When time comes to show it, set it to not hidden then use UIView animation to make the container width go from 0 to full table width. Set the duration pretty low (i.e. 0.2 seconds) so it's zippy. When you run the animation, the swipe-menu shows up over everything else in the cell content view. To make it disappear just reverse it (set the width to 0 in a UIView BeginAnimation block). You may also want to set an animation completion handler at the end and do some housekeeping there (set the container view to hidden, release memory, etc).

Ramin
Thanks... Havent' yet tried... but looks very promising...
Mugunth Kumar
A: 

@Ramin your suggestion was the path that I was taking as well, but I am having a little bit of an issue.

My "control view" isn't showing up when I swipe the cell, but I know that my swipes are detected through NSLog. The cells are built programmatically with UIView Subclass and then a subclass of UITableViewCell. The "control view" for each cell is also a subclass of UIView.

Why isn't the "control view" showing up when the swipe is detected? Am I calling [self.contentView setNeedsDisplay] in the wrong place?

//Control View UIView Subclass
//

#import "EmployeeListControlView.h"


@implementation EmployeeListControlView

@synthesize editing;

- (id)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {
        self.opaque          = YES;
        self.backgroundColor = [UIColor blackColor];
    }

    return self;
}

- (void)drawRect:(CGRect)rect {

    // Color and font for the main text items
    UIColor *mainTextColor = nil;
    UIFont *mainFont       = [UIFont boldSystemFontOfSize:16];

    // Color and font for the secondary text items (GMT offset, day)
    UIColor *secondaryTextColor = nil;
    UIFont *secondaryFont       = [UIFont systemFontOfSize:12];

    // Choose font color based on highlighted state.
    if (self.highlighted) {
        mainTextColor      = [UIColor whiteColor];
        secondaryTextColor = [UIColor whiteColor];
    } else {
        mainTextColor        = [UIColor whiteColor];
        secondaryTextColor   = [UIColor whiteColor];
        self.backgroundColor = [UIColor blackColor];
    }

    CGRect contentRect = self.bounds;

    // In this example we will never be editing, but this illustrates the appropriate pattern.
    if (!self.editing) {

        CGPoint point;

        // Set the color for the main text items.
        [mainTextColor set];

        point = CGPointMake(5, 2);
        [@"Item One" drawAtPoint:point 
                        forWidth:contentRect.size.width 
                        withFont:mainFont 
                     minFontSize:14 
                  actualFontSize:NULL 
                   lineBreakMode:UILineBreakModeTailTruncation 
              baselineAdjustment:UIBaselineAdjustmentAlignBaselines];

        point = CGPointMake(5, 20);
        [@"Item Two" drawAtPoint:point 
                        forWidth:contentRect.size.width 
                        withFont:secondaryFont 
                     minFontSize:12 
                  actualFontSize:NULL 
                   lineBreakMode:UILineBreakModeTailTruncation 
              baselineAdjustment:UIBaselineAdjustmentAlignBaselines];

        // Set the color for the secondary text items.
        [secondaryTextColor set];
    }
}

- (void)dealloc {
    [super dealloc];
}

- (BOOL)isHighlighted {
    return highlighted;
}

- (void)setHighlighted:(BOOL)lit {
    // If highlighted state changes, need to redisplay.
    if (highlighted != lit) {
        highlighted = lit; 
        [self setNeedsDisplay];
    }
}

@end


// Custom cell UITableViewCell subclass
//


#import "EmployeeCustomCell.h"


@implementation EmployeeCustomCell

@synthesize employeeListView;
@synthesize thumbnailImage;
@synthesize employeeControlView;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]) {

        /**
         * @todo
         * don't use hard coded values for frame
         */
        CGRect elvFrame = CGRectMake(2.0, 2.0, 300.0, self.contentView.bounds.size.height);
        CGRect elcFrame = CGRectMake(0, 0, 0, self.contentView.bounds.size.height);

        employeeListView    = [[EmployeeListCustomView alloc] initWithFrame:elvFrame];
        employeeControlView = [[EmployeeListControlView alloc] initWithFrame:elcFrame];

        employeeListView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

        self.selectionStyle = UITableViewCellSelectionStyleGray;

        [self.contentView addSubview:employeeListView];
        [self.contentView addSubview:employeeControlView];
        [self.contentView bringSubviewToFront:employeeControlView];
        self.employeeControlView.hidden = YES;
    }

    return self;
}

- (void)setEmployeeObject:(Employee *)newEmployeeObject {
    [employeeListView setEmpObject:newEmployeeObject];
    [self redisplay];
}

- (void)layoutSubviews {

    [super layoutSubviews];

    CGRect contentRect = self.contentView.bounds;

    if (self.editing) {

        CGFloat boundsX = contentRect.origin.x;
        CGRect frame;

        frame = CGRectMake(boundsX + 5, 0, 48, 48);
        self.thumbnailImage.frame = frame;
    }
}

- (void)redisplay {
    [employeeListView setNeedsDisplay];
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
}

- (void)dealloc {
    [employeeListView release];
    [employeeControlView release];
    [thumbnailImage release];
    [super dealloc];
}

#pragma mark -
#pragma mark Touch Controls

#define HORIZ_SWIPE_DRAG_MIN  12
#define VERT_SWIPE_DRAG_MAX    4

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch    = [touches anyObject];
    gestureStartPoint = [touch locationInView:self.contentView];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch          = [touches anyObject];
    CGPoint currentPosition = [touch locationInView:self.contentView];

    CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);
    CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);


    if (deltaX >= HORIZ_SWIPE_DRAG_MIN && deltaY <= VERT_SWIPE_DRAG_MAX) {

        NSLog(@"horizontal swipe");

        self.employeeControlView.hidden = NO;

        CGRect ecvFrame = self.employeeControlView.frame;

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:.02];

        ecvFrame.size.width = self.contentView.bounds.size.width;
        self.employeeControlView.frame = ecvFrame;

        [UIView commitAnimations];

        [self.contentView setNeedsDisplay];

    } else if (deltaY >= HORIZ_SWIPE_DRAG_MIN && deltaX <= VERT_SWIPE_DRAG_MAX) {
        NSLog(@"vertical swipe");
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    //  gestureStartPoint = 0.0;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    //  gestureStartPoint = 0.0;  
}
@end
Cory Wiles
+2  A: 

I've done a tweetie like menu, there's no full code but i blogged about it. Hope it helps!

http://petersteinberger.com/2010/01/tweetie-like-swipe-menu-for-iphone-apps/

steipete