mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Adding gestures to story titles. Needs refactoring to actually perform save/read commands. Also needs to hit the feed list.
This commit is contained in:
parent
d7900fdcfa
commit
f036fb799c
7 changed files with 999 additions and 223 deletions
|
@ -8,9 +8,9 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
#import "ABTableViewCell.h"
|
||||
#import "MCSwipeTableViewCell.h"
|
||||
|
||||
@interface FeedDetailTableCell : ABTableViewCell {
|
||||
@interface FeedDetailTableCell : MCSwipeTableViewCell {
|
||||
NewsBlurAppDelegate *appDelegate;
|
||||
|
||||
// All views
|
||||
|
@ -53,5 +53,12 @@
|
|||
@property (readwrite) BOOL hasAlpha;
|
||||
|
||||
- (UIImage *)imageByApplyingAlpha:(UIImage *)image withAlpha:(CGFloat) alpha;
|
||||
|
||||
- (void)setupGestures;
|
||||
|
||||
@end
|
||||
|
||||
@interface FeedDetailTableCellView : UIView
|
||||
|
||||
@property (nonatomic) FeedDetailTableCell *cell;
|
||||
|
||||
@end
|
|
@ -11,10 +11,12 @@
|
|||
#import "ABTableViewCell.h"
|
||||
#import "UIView+TKCategory.h"
|
||||
#import "Utilities.h"
|
||||
#import "MCSwipeTableViewCell.h"
|
||||
|
||||
static UIFont *textFont = nil;
|
||||
static UIFont *indicatorFont = nil;
|
||||
|
||||
@class FeedDetailViewController;
|
||||
|
||||
@implementation FeedDetailTableCell
|
||||
|
||||
|
@ -45,216 +47,6 @@ static UIFont *indicatorFont = nil;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)drawContentView:(CGRect)r highlighted:(BOOL)highlighted {
|
||||
|
||||
|
||||
int adjustForSocial = 3;
|
||||
if (self.isRiverOrSocial) {
|
||||
adjustForSocial = 20;
|
||||
}
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGRect rect = CGRectInset(r, 12, 12);
|
||||
rect.size.width -= 18; // Scrollbar padding
|
||||
|
||||
UIColor *backgroundColor;
|
||||
backgroundColor = highlighted ? UIColorFromRGB(0xFFFDEF) : UIColorFromRGB(0xf4f4f4);
|
||||
[backgroundColor set];
|
||||
|
||||
CGContextFillRect(context, r);
|
||||
|
||||
if (highlighted) {
|
||||
// [NewsBlurAppDelegate fillGradient:r startColor:UIColorFromRGB(0xFFFDEF) endColor:UIColorFromRGB(0xFFFDDF)];
|
||||
}
|
||||
|
||||
UIColor *textColor;
|
||||
UIFont *font;
|
||||
|
||||
if (self.isRead) {
|
||||
font = [UIFont fontWithName:@"Helvetica" size:11];
|
||||
textColor = UIColorFromRGB(0x808080);
|
||||
} else {
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:11];
|
||||
textColor = UIColorFromRGB(0x606060);
|
||||
|
||||
}
|
||||
if (highlighted) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
paragraphStyle.alignment = NSTextAlignmentLeft;
|
||||
|
||||
if (self.isRiverOrSocial) {
|
||||
[self.siteTitle drawInRect:CGRectMake(leftMargin + 20, 7, rect.size.width - 20, 21)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
|
||||
if (self.isRead) {
|
||||
font = [UIFont fontWithName:@"Helvetica" size:12];
|
||||
textColor = UIColorFromRGB(0x606060);
|
||||
|
||||
} else {
|
||||
textColor = UIColorFromRGB(0x333333);
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:12];
|
||||
}
|
||||
if (highlighted) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
}
|
||||
|
||||
// story title
|
||||
CGSize theSize = [self.storyTitle
|
||||
boundingRectWithSize:CGSizeMake(rect.size.width, 30.0)
|
||||
options:nil
|
||||
attributes:@{NSFontAttributeName: font,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}
|
||||
context:nil].size;
|
||||
|
||||
int storyTitleY = 7 + adjustForSocial + ((30 - theSize.height)/2);
|
||||
if (self.isShort) {
|
||||
storyTitleY = 7 + adjustForSocial + 2;
|
||||
}
|
||||
int storyTitleX = leftMargin;
|
||||
if (self.isStarred) {
|
||||
UIImage *savedIcon = [UIImage imageNamed:@"clock"];
|
||||
[savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1];
|
||||
storyTitleX += 20;
|
||||
}
|
||||
if (self.isShared) {
|
||||
UIImage *savedIcon = [UIImage imageNamed:@"menu_icn_share"];
|
||||
[savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1];
|
||||
storyTitleX += 20;
|
||||
}
|
||||
[self.storyTitle drawInRect:CGRectMake(storyTitleX, storyTitleY, rect.size.width - storyTitleX + leftMargin, theSize.height)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
|
||||
int storyAuthorDateY = 41 + adjustForSocial;
|
||||
if (self.isShort) {
|
||||
storyAuthorDateY -= 13;
|
||||
}
|
||||
|
||||
// story author style
|
||||
if (self.isRead) {
|
||||
textColor = UIColorFromRGB(0x959595);
|
||||
font = [UIFont fontWithName:@"Helvetica" size:10];
|
||||
} else {
|
||||
textColor = UIColorFromRGB(0xA6A8A2);
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
||||
}
|
||||
if (highlighted) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
|
||||
[self.storyAuthor
|
||||
drawInRect:CGRectMake(leftMargin, storyAuthorDateY, (rect.size.width) / 2 - 10, 15.0)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
// story date
|
||||
if (self.isRead) {
|
||||
textColor = UIColorFromRGB(0xbabdd1);
|
||||
font = [UIFont fontWithName:@"Helvetica" size:10];
|
||||
} else {
|
||||
textColor = UIColorFromRGB(0x262c6c);
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
||||
}
|
||||
|
||||
if (highlighted) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
|
||||
paragraphStyle.alignment = NSTextAlignmentRight;
|
||||
[self.storyDate
|
||||
drawInRect:CGRectMake(leftMargin + (rect.size.width) / 2 - 10, storyAuthorDateY, (rect.size.width) / 2 + 10, 15.0)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
// feed bar
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([self.feedColorBarTopBorder CGColor]));
|
||||
if (self.isRead) {
|
||||
CGContextSetAlpha(context, 0.15);
|
||||
}
|
||||
CGContextSetLineWidth(context, 4.0f);
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 2.0f, 1.0f);
|
||||
CGContextAddLineToPoint(context, 2.0f, self.frame.size.height - 1);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([self.feedColorBar CGColor]));
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 6.0f, 1.0f);
|
||||
CGContextAddLineToPoint(context, 6.0, self.frame.size.height - 1);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
// reset for borders
|
||||
|
||||
CGContextSetAlpha(context, 1.0);
|
||||
CGContextSetLineWidth(context, 1.0f);
|
||||
if (highlighted) {
|
||||
// top border
|
||||
UIColor *blue = UIColorFromRGB(0xF9F8F4);
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([blue CGColor]));
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0, 0.5f);
|
||||
CGContextAddLineToPoint(context, self.bounds.size.width, 0.5f);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
// bottom border
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0, self.bounds.size.height - 1.5f);
|
||||
CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height - 1.5f);
|
||||
CGContextStrokePath(context);
|
||||
} else {
|
||||
// top border
|
||||
UIColor *white = UIColorFromRGB(0xffffff);
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([white CGColor]));
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0.0f, 0.5f);
|
||||
CGContextAddLineToPoint(context, self.bounds.size.width, 0.5f);
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
// site favicon
|
||||
if (self.isRead && !self.hasAlpha) {
|
||||
if (self.isRiverOrSocial) {
|
||||
self.siteFavicon = [self imageByApplyingAlpha:self.siteFavicon withAlpha:0.25];
|
||||
}
|
||||
self.hasAlpha = YES;
|
||||
}
|
||||
|
||||
if (self.isRiverOrSocial) {
|
||||
[self.siteFavicon drawInRect:CGRectMake(leftMargin, 6.0, 16.0, 16.0)];
|
||||
}
|
||||
|
||||
// story indicator
|
||||
int storyIndicatorY = 4 + adjustForSocial;
|
||||
if (self.isShort){
|
||||
storyIndicatorY = 4 + adjustForSocial - 5 ;
|
||||
}
|
||||
|
||||
UIImage *unreadIcon;
|
||||
if (storyScore == -1) {
|
||||
unreadIcon = [UIImage imageNamed:@"g_icn_hidden"];
|
||||
} else if (storyScore == 1) {
|
||||
unreadIcon = [UIImage imageNamed:@"g_icn_focus"];
|
||||
} else {
|
||||
unreadIcon = [UIImage imageNamed:@"g_icn_unread"];
|
||||
}
|
||||
|
||||
[unreadIcon drawInRect:CGRectMake(15, storyIndicatorY + 14, 8, 8) blendMode:nil alpha:(self.isRead ? .15 : 1)];
|
||||
}
|
||||
|
||||
- (UIImage *)imageByApplyingAlpha:(UIImage *)image withAlpha:(CGFloat) alpha {
|
||||
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0f);
|
||||
|
||||
|
@ -277,5 +69,277 @@ static UIFont *indicatorFont = nil;
|
|||
return newImage;
|
||||
}
|
||||
|
||||
- (void)setupGestures {
|
||||
NSString *unreadIcon;
|
||||
if (storyScore == -1) {
|
||||
unreadIcon = @"g_icn_hidden.png";
|
||||
} else if (storyScore == 1) {
|
||||
unreadIcon = @"g_icn_focus.png";
|
||||
} else {
|
||||
unreadIcon = @"g_icn_unread.png";
|
||||
}
|
||||
|
||||
appDelegate = [NewsBlurAppDelegate sharedAppDelegate];
|
||||
[self setDelegate:appDelegate.feedDetailViewController];
|
||||
[self setFirstStateIconName:@"clock.png"
|
||||
firstColor:[UIColor colorWithRed:85.0 / 255.0 green:213.0 / 255.0 blue:80.0 / 255.0 alpha:1.0]
|
||||
secondStateIconName:nil
|
||||
secondColor:nil
|
||||
thirdIconName:unreadIcon
|
||||
thirdColor:[UIColor colorWithRed:254.0 / 255.0 green:217.0 / 255.0 blue:56.0 / 255.0 alpha:1.0]
|
||||
fourthIconName:nil
|
||||
fourthColor:nil];
|
||||
|
||||
// [self.contentView setBackgroundColor:[UIColor whiteColor]];
|
||||
|
||||
// Setting the default inactive state color to the tableView background color
|
||||
// [self setDefaultColor:self.tableView.backgroundView.backgroundColor];
|
||||
|
||||
//
|
||||
[self setSelectionStyle:UITableViewCellSelectionStyleGray];
|
||||
|
||||
self.mode = MCSwipeTableViewCellModeSwitch;
|
||||
self.shouldAnimatesIcons = NO;
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplay {
|
||||
[super setNeedsDisplay];
|
||||
for (UIView *view in self.contentView.subviews) {
|
||||
[view setNeedsDisplay];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setNeedsLayout {
|
||||
[super setNeedsLayout];
|
||||
for (UIView *view in self.contentView.subviews) {
|
||||
[view setNeedsLayout];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setSelected:(BOOL)selected animated:(BOOL)animated {
|
||||
[super setSelected:selected animated:NO];
|
||||
|
||||
if (animated) {
|
||||
[CATransaction begin];
|
||||
CATransition* animation = [CATransition animation];
|
||||
animation.type = kCATransitionFade;
|
||||
animation.duration = 0.6;
|
||||
[animation setTimingFunction:[CAMediaTimingFunction
|
||||
functionWithName:kCAMediaTimingFunctionDefault]];
|
||||
[self.contentView.layer addAnimation:animation forKey:@"deselectRow"];
|
||||
[CATransaction commit];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FeedDetailTableCellView
|
||||
|
||||
@synthesize cell;
|
||||
|
||||
- (void)drawRect:(CGRect)r {
|
||||
int adjustForSocial = 3;
|
||||
if (cell.isRiverOrSocial) {
|
||||
adjustForSocial = 20;
|
||||
}
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGRect rect = CGRectInset(r, 12, 12);
|
||||
rect.size.width -= 18; // Scrollbar padding
|
||||
|
||||
UIColor *backgroundColor;
|
||||
backgroundColor = cell.highlighted || cell.selected ?
|
||||
UIColorFromRGB(0xFFFDEF) : UIColorFromRGB(0xf4f4f4);
|
||||
[backgroundColor set];
|
||||
|
||||
CGContextFillRect(context, r);
|
||||
|
||||
UIColor *textColor;
|
||||
UIFont *font;
|
||||
|
||||
if (cell.isRead) {
|
||||
font = [UIFont fontWithName:@"Helvetica" size:11];
|
||||
textColor = UIColorFromRGB(0x808080);
|
||||
} else {
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:11];
|
||||
textColor = UIColorFromRGB(0x606060);
|
||||
|
||||
}
|
||||
if (cell.highlighted || cell.selected) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
paragraphStyle.alignment = NSTextAlignmentLeft;
|
||||
|
||||
if (cell.isRiverOrSocial) {
|
||||
[cell.siteTitle drawInRect:CGRectMake(leftMargin + 20, 7, rect.size.width - 20, 21)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
|
||||
if (cell.isRead) {
|
||||
font = [UIFont fontWithName:@"Helvetica" size:12];
|
||||
textColor = UIColorFromRGB(0x606060);
|
||||
|
||||
} else {
|
||||
textColor = UIColorFromRGB(0x333333);
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:12];
|
||||
}
|
||||
if (cell.highlighted || cell.selected) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
}
|
||||
|
||||
// story title
|
||||
CGSize theSize = [cell.storyTitle
|
||||
boundingRectWithSize:CGSizeMake(rect.size.width, 30.0)
|
||||
options:nil
|
||||
attributes:@{NSFontAttributeName: font,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}
|
||||
context:nil].size;
|
||||
|
||||
int storyTitleY = 7 + adjustForSocial + ((30 - theSize.height)/2);
|
||||
if (cell.isShort) {
|
||||
storyTitleY = 7 + adjustForSocial + 2;
|
||||
}
|
||||
int storyTitleX = leftMargin;
|
||||
if (cell.isStarred) {
|
||||
UIImage *savedIcon = [UIImage imageNamed:@"clock"];
|
||||
[savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1];
|
||||
storyTitleX += 20;
|
||||
}
|
||||
if (cell.isShared) {
|
||||
UIImage *savedIcon = [UIImage imageNamed:@"menu_icn_share"];
|
||||
[savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1];
|
||||
storyTitleX += 20;
|
||||
}
|
||||
[cell.storyTitle drawInRect:CGRectMake(storyTitleX, storyTitleY, rect.size.width - storyTitleX + leftMargin, theSize.height)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
|
||||
int storyAuthorDateY = 41 + adjustForSocial;
|
||||
if (cell.isShort) {
|
||||
storyAuthorDateY -= 13;
|
||||
}
|
||||
|
||||
// story author style
|
||||
if (cell.isRead) {
|
||||
textColor = UIColorFromRGB(0x959595);
|
||||
font = [UIFont fontWithName:@"Helvetica" size:10];
|
||||
} else {
|
||||
textColor = UIColorFromRGB(0xA6A8A2);
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
||||
}
|
||||
if (cell.highlighted || cell.selected) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
|
||||
[cell.storyAuthor
|
||||
drawInRect:CGRectMake(leftMargin, storyAuthorDateY, (rect.size.width) / 2 - 10, 15.0)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
// story date
|
||||
if (cell.isRead) {
|
||||
textColor = UIColorFromRGB(0xbabdd1);
|
||||
font = [UIFont fontWithName:@"Helvetica" size:10];
|
||||
} else {
|
||||
textColor = UIColorFromRGB(0x262c6c);
|
||||
font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
||||
}
|
||||
|
||||
if (cell.highlighted || cell.selected) {
|
||||
textColor = UIColorFromRGB(0x686868);
|
||||
}
|
||||
|
||||
paragraphStyle.alignment = NSTextAlignmentRight;
|
||||
[cell.storyDate
|
||||
drawInRect:CGRectMake(leftMargin + (rect.size.width) / 2 - 10, storyAuthorDateY, (rect.size.width) / 2 + 10, 15.0)
|
||||
withAttributes:@{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: textColor,
|
||||
NSParagraphStyleAttributeName: paragraphStyle}];
|
||||
// feed bar
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([cell.feedColorBarTopBorder CGColor]));
|
||||
if (cell.isRead) {
|
||||
CGContextSetAlpha(context, 0.15);
|
||||
}
|
||||
CGContextSetLineWidth(context, 4.0f);
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 2.0f, 1.0f);
|
||||
CGContextAddLineToPoint(context, 2.0f, cell.frame.size.height - 1);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([cell.feedColorBar CGColor]));
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 6.0f, 1.0f);
|
||||
CGContextAddLineToPoint(context, 6.0, cell.frame.size.height - 1);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
// reset for borders
|
||||
|
||||
CGContextSetAlpha(context, 1.0);
|
||||
CGContextSetLineWidth(context, 1.0f);
|
||||
if (cell.highlighted || cell.selected) {
|
||||
// top border
|
||||
UIColor *blue = UIColorFromRGB(0xF9F8F4);
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([blue CGColor]));
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0, 0.5f);
|
||||
CGContextAddLineToPoint(context, cell.bounds.size.width, 0.5f);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
// bottom border
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0, cell.bounds.size.height - .5f);
|
||||
CGContextAddLineToPoint(context, cell.bounds.size.width, cell.bounds.size.height - .5f);
|
||||
CGContextStrokePath(context);
|
||||
} else {
|
||||
// top border
|
||||
UIColor *white = UIColorFromRGB(0xffffff);
|
||||
|
||||
CGContextSetStrokeColor(context, CGColorGetComponents([white CGColor]));
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0.0f, 0.5f);
|
||||
CGContextAddLineToPoint(context, cell.bounds.size.width, 0.5f);
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
// site favicon
|
||||
if (cell.isRead && !cell.hasAlpha) {
|
||||
if (cell.isRiverOrSocial) {
|
||||
cell.siteFavicon = [cell imageByApplyingAlpha:cell.siteFavicon withAlpha:0.25];
|
||||
}
|
||||
cell.hasAlpha = YES;
|
||||
}
|
||||
|
||||
if (cell.isRiverOrSocial) {
|
||||
[cell.siteFavicon drawInRect:CGRectMake(leftMargin, 6.0, 16.0, 16.0)];
|
||||
}
|
||||
|
||||
// story indicator
|
||||
int storyIndicatorY = 4 + adjustForSocial;
|
||||
if (cell.isShort){
|
||||
storyIndicatorY = 4 + adjustForSocial - 5 ;
|
||||
}
|
||||
|
||||
UIImage *unreadIcon;
|
||||
if (cell.storyScore == -1) {
|
||||
unreadIcon = [UIImage imageNamed:@"g_icn_hidden"];
|
||||
} else if (cell.storyScore == 1) {
|
||||
unreadIcon = [UIImage imageNamed:@"g_icn_focus"];
|
||||
} else {
|
||||
unreadIcon = [UIImage imageNamed:@"g_icn_unread"];
|
||||
}
|
||||
|
||||
[unreadIcon drawInRect:CGRectMake(15, storyIndicatorY + 14, 8, 8) blendMode:nil alpha:(cell.isRead ? .15 : 1)];
|
||||
}
|
||||
|
||||
@end
|
|
@ -14,15 +14,17 @@
|
|||
#import "WEPopoverController.h"
|
||||
#import "TransparentToolbar.h"
|
||||
#import "NBNotifier.h"
|
||||
#import "MCSwipeTableViewCell.h"
|
||||
|
||||
@class NewsBlurAppDelegate;
|
||||
@class FeedDetailTableCell;
|
||||
@class MCSwipeTableViewCell;
|
||||
|
||||
@interface FeedDetailViewController : BaseViewController
|
||||
<UITableViewDelegate, UITableViewDataSource,
|
||||
UIActionSheetDelegate, UIAlertViewDelegate,
|
||||
UIPopoverControllerDelegate, ASIHTTPRequestDelegate,
|
||||
WEPopoverControllerDelegate> {
|
||||
WEPopoverControllerDelegate, MCSwipeTableViewCellDelegate> {
|
||||
NewsBlurAppDelegate *appDelegate;
|
||||
|
||||
int feedPage;
|
||||
|
|
|
@ -852,23 +852,23 @@
|
|||
NSString *cellIdentifier;
|
||||
NSDictionary *feed ;
|
||||
|
||||
if (indexPath.row >= appDelegate.storyLocationsCount) {
|
||||
return [self makeLoadingCell];
|
||||
}
|
||||
|
||||
if (appDelegate.isRiverView || appDelegate.isSocialView) {
|
||||
cellIdentifier = @"FeedRiverDetailCellIdentifier";
|
||||
} else {
|
||||
cellIdentifier = @"FeedDetailCellIdentifier";
|
||||
}
|
||||
|
||||
FeedDetailTableCell *cell = (FeedDetailTableCell *)[tableView
|
||||
dequeueReusableCellWithIdentifier:cellIdentifier];
|
||||
FeedDetailTableCell *cell = (FeedDetailTableCell *)[tableView
|
||||
dequeueReusableCellWithIdentifier:cellIdentifier];
|
||||
if (cell == nil) {
|
||||
cell = [[FeedDetailTableCell alloc] initWithStyle:UITableViewCellStyleDefault
|
||||
reuseIdentifier:nil];
|
||||
}
|
||||
|
||||
if (indexPath.row >= appDelegate.storyLocationsCount) {
|
||||
return [self makeLoadingCell];
|
||||
}
|
||||
|
||||
|
||||
NSDictionary *story = [self getStoryAtRow:indexPath.row];
|
||||
|
||||
id feedId = [story objectForKey:@"story_feed_id"];
|
||||
|
@ -951,14 +951,21 @@
|
|||
cell.isRiverOrSocial = YES;
|
||||
}
|
||||
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
NSInteger rowIndex = [appDelegate locationOfActiveStory];
|
||||
if (rowIndex == indexPath.row) {
|
||||
[self.storyTitlesTable selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
|
||||
}
|
||||
}
|
||||
|
||||
FeedDetailTableCellView *content = [[FeedDetailTableCellView alloc]
|
||||
initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, [self tableView:self.storyTitlesTable heightForRowAtIndexPath:indexPath])];
|
||||
content.cell = cell;
|
||||
[cell.contentView addSubview:content];
|
||||
[content sizeToFit];
|
||||
[cell setupGestures];
|
||||
|
||||
return cell;
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)loadStory:(FeedDetailTableCell *)cell atRow:(NSInteger)row {
|
||||
|
@ -1076,6 +1083,29 @@
|
|||
return [appDelegate.activeFeedStories objectAtIndex:row];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - MCSwipeTableViewCellDelegate
|
||||
|
||||
// When the user starts swiping the cell this method is called
|
||||
- (void)swipeTableViewCellDidStartSwiping:(MCSwipeTableViewCell *)cell {
|
||||
NSLog(@"Did start swiping the cell!");
|
||||
}
|
||||
|
||||
/*
|
||||
// When the user is dragging, this method is called and return the dragged percentage from the border
|
||||
- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didSwipWithPercentage:(CGFloat)percentage {
|
||||
NSLog(@"Did swipe with percentage : %f", percentage);
|
||||
}
|
||||
*/
|
||||
|
||||
- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state mode:(MCSwipeTableViewCellMode)mode {
|
||||
NSLog(@"Did end swipping with IndexPath : %@ - MCSwipeTableViewCellState : %d - MCSwipeTableViewCellMode : %d", [self.storyTitlesTable indexPathForCell:cell], state, mode);
|
||||
|
||||
if (mode == MCSwipeTableViewCellModeExit) {
|
||||
[self.storyTitlesTable deleteRowsAtIndexPaths:@[[self.storyTitlesTable indexPathForCell:cell]] withRowAnimation:UITableViewRowAnimationFade];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Feed Actions
|
||||
|
||||
|
|
|
@ -350,6 +350,7 @@
|
|||
FFCDD8F717F4BCB4000C6483 /* Default-portrait@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFCDD8F117F4BCB4000C6483 /* Default-portrait@2x.png */; };
|
||||
FFCDD8F817F4BCB4000C6483 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = FFCDD8F217F4BCB4000C6483 /* Default.png */; };
|
||||
FFCDD8FA17F50C08000C6483 /* drag_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = FFCDD8F917F50C08000C6483 /* drag_icon.png */; };
|
||||
FFCDD8FE17F6368F000C6483 /* MCSwipeTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFCDD8FD17F6368F000C6483 /* MCSwipeTableViewCell.m */; };
|
||||
FFD1D7311459B63500E46F89 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD1D7301459B63500E46F89 /* BaseViewController.m */; };
|
||||
FFD887F01445F1E800385399 /* AddSiteAutocompleteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD887EE1445F1E800385399 /* AddSiteAutocompleteCell.m */; };
|
||||
FFDCA0AF16E80866000D8E0C /* DEComposeRuledView.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDCA0A516E80866000D8E0C /* DEComposeRuledView.m */; };
|
||||
|
@ -917,6 +918,8 @@
|
|||
FFCDD8F117F4BCB4000C6483 /* Default-portrait@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-portrait@2x.png"; sourceTree = "<group>"; };
|
||||
FFCDD8F217F4BCB4000C6483 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
|
||||
FFCDD8F917F50C08000C6483 /* drag_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = drag_icon.png; sourceTree = "<group>"; };
|
||||
FFCDD8FC17F6368F000C6483 /* MCSwipeTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSwipeTableViewCell.h; sourceTree = "<group>"; };
|
||||
FFCDD8FD17F6368F000C6483 /* MCSwipeTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCSwipeTableViewCell.m; sourceTree = "<group>"; };
|
||||
FFD1D72F1459B63500E46F89 /* BaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseViewController.h; sourceTree = "<group>"; };
|
||||
FFD1D7301459B63500E46F89 /* BaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseViewController.m; sourceTree = "<group>"; };
|
||||
FFD887ED1445F1E800385399 /* AddSiteAutocompleteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddSiteAutocompleteCell.h; sourceTree = "<group>"; };
|
||||
|
@ -1091,6 +1094,7 @@
|
|||
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFCDD8FB17F6368F000C6483 /* MCSwipeTableViewCell */,
|
||||
FF5D40091799F70200349659 /* ARChromeActivity */,
|
||||
FFAF53951799E69D00C7FCCB /* PocketSDK */,
|
||||
FFAF53A61799E69D00C7FCCB /* ReadabilityActivity */,
|
||||
|
@ -1943,6 +1947,16 @@
|
|||
path = logos;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FFCDD8FB17F6368F000C6483 /* MCSwipeTableViewCell */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFCDD8FC17F6368F000C6483 /* MCSwipeTableViewCell.h */,
|
||||
FFCDD8FD17F6368F000C6483 /* MCSwipeTableViewCell.m */,
|
||||
);
|
||||
name = MCSwipeTableViewCell;
|
||||
path = "Other Sources/MCSwipeTableViewCell";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FFDCA0A316E80866000D8E0C /* REComposeViewController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2400,6 +2414,7 @@
|
|||
78095E35128EF30D00230C8E /* ASIDownloadCache.m in Sources */,
|
||||
78095E36128EF30D00230C8E /* ASIFormDataRequest.m in Sources */,
|
||||
78095E37128EF30D00230C8E /* ASIHTTPRequest.m in Sources */,
|
||||
FFCDD8FE17F6368F000C6483 /* MCSwipeTableViewCell.m in Sources */,
|
||||
78095E38128EF30D00230C8E /* ASIInputStream.m in Sources */,
|
||||
78095E39128EF30D00230C8E /* ASINetworkQueue.m in Sources */,
|
||||
78095EC9128F30B500230C8E /* OriginalStoryViewController.m in Sources */,
|
||||
|
|
99
clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.h
Executable file
99
clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.h
Executable file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// MCSwipeTableViewCell.h
|
||||
// MCSwipeTableViewCell
|
||||
//
|
||||
// Created by Ali Karagoz on 24/02/13.
|
||||
// Copyright (c) 2013 Mad Castle. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class MCSwipeTableViewCell;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MCSwipeTableViewCellState){
|
||||
MCSwipeTableViewCellStateNone = 0,
|
||||
MCSwipeTableViewCellState1,
|
||||
MCSwipeTableViewCellState2,
|
||||
MCSwipeTableViewCellState3,
|
||||
MCSwipeTableViewCellState4
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MCSwipeTableViewCellDirection){
|
||||
MCSwipeTableViewCellDirectionLeft = 0,
|
||||
MCSwipeTableViewCellDirectionCenter,
|
||||
MCSwipeTableViewCellDirectionRight
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MCSwipeTableViewCellMode){
|
||||
MCSwipeTableViewCellModeNone = 0,
|
||||
MCSwipeTableViewCellModeExit,
|
||||
MCSwipeTableViewCellModeSwitch
|
||||
};
|
||||
|
||||
@protocol MCSwipeTableViewCellDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
// When the user starts swiping the cell this method is called
|
||||
- (void)swipeTableViewCellDidStartSwiping:(MCSwipeTableViewCell *)cell;
|
||||
|
||||
// When the user is dragging, this method is called and return the dragged percentage from the border
|
||||
- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didSwipWithPercentage:(CGFloat)percentage;
|
||||
|
||||
// When the user releases the cell, after swiping it, this method is called
|
||||
- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state mode:(MCSwipeTableViewCellMode)mode;
|
||||
|
||||
@end
|
||||
|
||||
@interface MCSwipeTableViewCell : UITableViewCell
|
||||
|
||||
@property (nonatomic, assign) id <MCSwipeTableViewCellDelegate> delegate;
|
||||
|
||||
@property (nonatomic, copy) NSString *firstIconName;
|
||||
@property (nonatomic, copy) NSString *secondIconName;
|
||||
@property (nonatomic, copy) NSString *thirdIconName;
|
||||
@property (nonatomic, copy) NSString *fourthIconName;
|
||||
|
||||
@property (nonatomic, strong) UIColor *firstColor;
|
||||
@property (nonatomic, strong) UIColor *secondColor;
|
||||
@property (nonatomic, strong) UIColor *thirdColor;
|
||||
@property (nonatomic, strong) UIColor *fourthColor;
|
||||
|
||||
// Color for background, when any state hasn't triggered yet
|
||||
@property (nonatomic, strong) UIColor *defaultColor;
|
||||
|
||||
// This is the general mode for all states
|
||||
// If a specific mode for a state isn't defined, this mode will be taken in action
|
||||
@property (nonatomic, assign) MCSwipeTableViewCellMode mode;
|
||||
|
||||
// Individual mode for states
|
||||
@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState1;
|
||||
@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState2;
|
||||
@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState3;
|
||||
@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState4;
|
||||
|
||||
@property (nonatomic, assign) BOOL isDragging;
|
||||
@property (nonatomic, assign) BOOL shouldDrag;
|
||||
@property (nonatomic, assign) BOOL shouldAnimatesIcons;
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style
|
||||
reuseIdentifier:(NSString *)reuseIdentifier
|
||||
firstStateIconName:(NSString *)firstIconName
|
||||
firstColor:(UIColor *)firstColor
|
||||
secondStateIconName:(NSString *)secondIconName
|
||||
secondColor:(UIColor *)secondColor
|
||||
thirdIconName:(NSString *)thirdIconName
|
||||
thirdColor:(UIColor *)thirdColor
|
||||
fourthIconName:(NSString *)fourthIconName
|
||||
fourthColor:(UIColor *)fourthColor;
|
||||
|
||||
- (void)setFirstStateIconName:(NSString *)firstIconName
|
||||
firstColor:(UIColor *)firstColor
|
||||
secondStateIconName:(NSString *)secondIconName
|
||||
secondColor:(UIColor *)secondColor
|
||||
thirdIconName:(NSString *)thirdIconName
|
||||
thirdColor:(UIColor *)thirdColor
|
||||
fourthIconName:(NSString *)fourthIconName
|
||||
fourthColor:(UIColor *)fourthColor;
|
||||
|
||||
@end
|
559
clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.m
Executable file
559
clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.m
Executable file
|
@ -0,0 +1,559 @@
|
|||
//
|
||||
// MCSwipeTableViewCell.m
|
||||
// MCSwipeTableViewCell
|
||||
//
|
||||
// Created by Ali Karagoz on 24/02/13.
|
||||
// Copyright (c) 2013 Mad Castle. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MCSwipeTableViewCell.h"
|
||||
|
||||
static CGFloat const kMCStop1 = 0.15; // Percentage limit to trigger the first action
|
||||
static CGFloat const kMCStop2 = 0.75; // Percentage limit to trigger the second action
|
||||
static CGFloat const kMCBounceAmplitude = 20.0; // Maximum bounce amplitude when using the MCSwipeTableViewCellModeSwitch mode
|
||||
static NSTimeInterval const kMCBounceDuration1 = 0.2; // Duration of the first part of the bounce animation
|
||||
static NSTimeInterval const kMCBounceDuration2 = 0.1; // Duration of the second part of the bounce animation
|
||||
static NSTimeInterval const kMCDurationLowLimit = 0.25; // Lowest duration when swipping the cell because we try to simulate velocity
|
||||
static NSTimeInterval const kMCDurationHightLimit = 0.1; // Highest duration when swipping the cell because we try to simulate velocity
|
||||
|
||||
@interface MCSwipeTableViewCell () <UIGestureRecognizerDelegate>
|
||||
|
||||
@property (nonatomic, assign) MCSwipeTableViewCellDirection direction;
|
||||
@property (nonatomic, assign) CGFloat currentPercentage;
|
||||
|
||||
@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer;
|
||||
@property (nonatomic, strong) UIImageView *slidingImageView;
|
||||
@property (nonatomic, strong) NSString *currentImageName;
|
||||
@property (nonatomic, strong) UIView *colorIndicatorView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MCSwipeTableViewCell
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
|
||||
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
||||
if (self) {
|
||||
[self initializer];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if (self) {
|
||||
[self initializer];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self initializer];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Custom Initializer
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style
|
||||
reuseIdentifier:(NSString *)reuseIdentifier
|
||||
firstStateIconName:(NSString *)firstIconName
|
||||
firstColor:(UIColor *)firstColor
|
||||
secondStateIconName:(NSString *)secondIconName
|
||||
secondColor:(UIColor *)secondColor
|
||||
thirdIconName:(NSString *)thirdIconName
|
||||
thirdColor:(UIColor *)thirdColor
|
||||
fourthIconName:(NSString *)fourthIconName
|
||||
fourthColor:(UIColor *)fourthColor {
|
||||
|
||||
self = [self initWithStyle:style reuseIdentifier:reuseIdentifier];
|
||||
if (self) {
|
||||
[self setFirstStateIconName:firstIconName
|
||||
firstColor:firstColor
|
||||
secondStateIconName:secondIconName
|
||||
secondColor:secondColor
|
||||
thirdIconName:thirdIconName
|
||||
thirdColor:thirdColor
|
||||
fourthIconName:fourthIconName
|
||||
fourthColor:fourthColor];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initializer {
|
||||
|
||||
_mode = MCSwipeTableViewCellModeNone;
|
||||
|
||||
_colorIndicatorView = [[UIView alloc] initWithFrame:self.bounds];
|
||||
[_colorIndicatorView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
|
||||
[_colorIndicatorView setBackgroundColor:(self.defaultColor ? self.defaultColor : [UIColor clearColor])];
|
||||
[self insertSubview:_colorIndicatorView atIndex:0];
|
||||
|
||||
_slidingImageView = [[UIImageView alloc] init];
|
||||
[_slidingImageView setContentMode:UIViewContentModeCenter];
|
||||
[_colorIndicatorView addSubview:_slidingImageView];
|
||||
|
||||
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureRecognizer:)];
|
||||
[self addGestureRecognizer:_panGestureRecognizer];
|
||||
[_panGestureRecognizer setDelegate:self];
|
||||
|
||||
_isDragging = NO;
|
||||
|
||||
// By default the cells are draggable
|
||||
_shouldDrag = YES;
|
||||
|
||||
// By default the icons are animating
|
||||
_shouldAnimatesIcons = YES;
|
||||
|
||||
// Set state modes
|
||||
_modeForState1 = MCSwipeTableViewCellModeNone;
|
||||
_modeForState2 = MCSwipeTableViewCellModeNone;
|
||||
_modeForState3 = MCSwipeTableViewCellModeNone;
|
||||
_modeForState4 = MCSwipeTableViewCellModeNone;
|
||||
}
|
||||
|
||||
#pragma mark - Setter
|
||||
|
||||
- (void)setFirstStateIconName:(NSString *)firstIconName
|
||||
firstColor:(UIColor *)firstColor
|
||||
secondStateIconName:(NSString *)secondIconName
|
||||
secondColor:(UIColor *)secondColor
|
||||
thirdIconName:(NSString *)thirdIconName
|
||||
thirdColor:(UIColor *)thirdColor
|
||||
fourthIconName:(NSString *)fourthIconName
|
||||
fourthColor:(UIColor *)fourthColor {
|
||||
|
||||
[self setFirstIconName:firstIconName];
|
||||
[self setSecondIconName:secondIconName];
|
||||
[self setThirdIconName:thirdIconName];
|
||||
[self setFourthIconName:fourthIconName];
|
||||
|
||||
[self setFirstColor:firstColor];
|
||||
[self setSecondColor:secondColor];
|
||||
[self setThirdColor:thirdColor];
|
||||
[self setFourthColor:fourthColor];
|
||||
}
|
||||
|
||||
#pragma mark - Prepare reuse
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
|
||||
// Clearing before presenting back the cell to the user
|
||||
[_colorIndicatorView setBackgroundColor:[UIColor clearColor]];
|
||||
|
||||
// clearing the dragging flag
|
||||
_isDragging = NO;
|
||||
|
||||
// Before reuse we need to reset it's state
|
||||
_shouldDrag = YES;
|
||||
_shouldAnimatesIcons = YES;
|
||||
_mode = MCSwipeTableViewCellModeNone;
|
||||
_modeForState1 = MCSwipeTableViewCellModeNone;
|
||||
_modeForState2 = MCSwipeTableViewCellModeNone;
|
||||
_modeForState3 = MCSwipeTableViewCellModeNone;
|
||||
_modeForState4 = MCSwipeTableViewCellModeNone;
|
||||
}
|
||||
|
||||
#pragma mark - Handle Gestures
|
||||
|
||||
- (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)gesture {
|
||||
|
||||
// The user do not want you to be dragged!
|
||||
if (!_shouldDrag) return;
|
||||
|
||||
UIGestureRecognizerState state = [gesture state];
|
||||
CGPoint translation = [gesture translationInView:self];
|
||||
CGPoint velocity = [gesture velocityInView:self];
|
||||
CGFloat percentage = [self percentageWithOffset:CGRectGetMinX(self.contentView.frame) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
NSTimeInterval animationDuration = [self animationDurationWithVelocity:velocity];
|
||||
_direction = [self directionWithPercentage:percentage];
|
||||
|
||||
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged) {
|
||||
_isDragging = YES;
|
||||
|
||||
CGPoint center = {self.contentView.center.x + translation.x, self.contentView.center.y};
|
||||
NSLog(@"Center: %@", NSStringFromCGPoint(center));
|
||||
[self.contentView setCenter:center];
|
||||
[self animateWithOffset:CGRectGetMinX(self.contentView.frame)];
|
||||
[gesture setTranslation:CGPointZero inView:self];
|
||||
|
||||
// Notifying the delegate that we are dragging with an offset percentage
|
||||
if ([_delegate respondsToSelector:@selector(swipeTableViewCell:didSwipWithPercentage:)]) {
|
||||
[_delegate swipeTableViewCell:self didSwipWithPercentage:percentage];
|
||||
}
|
||||
}
|
||||
|
||||
else if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled) {
|
||||
_isDragging = NO;
|
||||
|
||||
_currentImageName = [self imageNameWithPercentage:percentage];
|
||||
_currentPercentage = percentage;
|
||||
|
||||
// Current state
|
||||
MCSwipeTableViewCellState cellState = [self stateWithPercentage:percentage];
|
||||
|
||||
// Current mode
|
||||
MCSwipeTableViewCellMode cellMode;
|
||||
|
||||
if (cellState == MCSwipeTableViewCellState1 && self.modeForState1 != MCSwipeTableViewCellModeNone) {
|
||||
cellMode = self.modeForState1;
|
||||
} else if (cellState == MCSwipeTableViewCellState2 && self.modeForState2 != MCSwipeTableViewCellModeNone) {
|
||||
cellMode = self.modeForState2;
|
||||
} else if (cellState == MCSwipeTableViewCellState3 && self.modeForState3 != MCSwipeTableViewCellModeNone) {
|
||||
cellMode = self.modeForState3;
|
||||
} else if (cellState == MCSwipeTableViewCellState4 && self.modeForState4 != MCSwipeTableViewCellModeNone) {
|
||||
cellMode = self.modeForState4;
|
||||
} else {
|
||||
cellMode = self.mode;
|
||||
}
|
||||
|
||||
if (cellMode == MCSwipeTableViewCellModeExit && _direction != MCSwipeTableViewCellDirectionCenter && [self validateState:cellState])
|
||||
[self moveWithDuration:animationDuration andDirection:_direction];
|
||||
else
|
||||
[self bounceToOrigin];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UIGestureRecognizerDelegate
|
||||
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
||||
if ([gestureRecognizer class] == [UIPanGestureRecognizer class]) {
|
||||
|
||||
UIPanGestureRecognizer *g = (UIPanGestureRecognizer *)gestureRecognizer;
|
||||
CGPoint point = [g velocityInView:self];
|
||||
|
||||
if (fabsf(point.x) > fabsf(point.y) ) {
|
||||
|
||||
// We notify the delegate that we just started dragging
|
||||
if ([_delegate respondsToSelector:@selector(swipeTableViewCellDidStartSwiping:)]) {
|
||||
[_delegate swipeTableViewCellDidStartSwiping:self];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - Utils
|
||||
- (CGFloat)offsetWithPercentage:(CGFloat)percentage relativeToWidth:(CGFloat)width {
|
||||
CGFloat offset = percentage * width;
|
||||
|
||||
if (offset < -width) offset = -width;
|
||||
else if (offset > width) offset = width;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
- (CGFloat)percentageWithOffset:(CGFloat)offset relativeToWidth:(CGFloat)width {
|
||||
CGFloat percentage = offset / width;
|
||||
|
||||
if (percentage < -1.0) percentage = -1.0;
|
||||
else if (percentage > 1.0) percentage = 1.0;
|
||||
|
||||
return percentage;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)animationDurationWithVelocity:(CGPoint)velocity {
|
||||
CGFloat width = CGRectGetWidth(self.bounds);
|
||||
NSTimeInterval animationDurationDiff = kMCDurationHightLimit - kMCDurationLowLimit;
|
||||
CGFloat horizontalVelocity = velocity.x;
|
||||
|
||||
if (horizontalVelocity < -width) horizontalVelocity = -width;
|
||||
else if (horizontalVelocity > width) horizontalVelocity = width;
|
||||
|
||||
return (kMCDurationHightLimit + kMCDurationLowLimit) - fabs(((horizontalVelocity / width) * animationDurationDiff));
|
||||
}
|
||||
|
||||
- (MCSwipeTableViewCellDirection)directionWithPercentage:(CGFloat)percentage {
|
||||
if (percentage < 0)
|
||||
return MCSwipeTableViewCellDirectionLeft;
|
||||
else if (percentage > 0)
|
||||
return MCSwipeTableViewCellDirectionRight;
|
||||
else
|
||||
return MCSwipeTableViewCellDirectionCenter;
|
||||
}
|
||||
|
||||
- (NSString *)imageNameWithPercentage:(CGFloat)percentage {
|
||||
NSString *imageName;
|
||||
|
||||
// Image
|
||||
if (percentage >= 0 && percentage < kMCStop2)
|
||||
imageName = _firstIconName;
|
||||
else if (percentage >= kMCStop2)
|
||||
imageName = _secondIconName;
|
||||
else if (percentage < 0 && percentage > -kMCStop2)
|
||||
imageName = _thirdIconName;
|
||||
else if (percentage <= -kMCStop2)
|
||||
imageName = _fourthIconName;
|
||||
|
||||
return imageName;
|
||||
}
|
||||
- (CGFloat)imageAlphaWithPercentage:(CGFloat)percentage {
|
||||
CGFloat alpha;
|
||||
|
||||
if (percentage >= 0 && percentage < kMCStop1)
|
||||
alpha = percentage / kMCStop1;
|
||||
else if (percentage < 0 && percentage > -kMCStop1)
|
||||
alpha = fabsf(percentage / kMCStop1);
|
||||
else alpha = 1.0;
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
- (UIColor *)colorWithPercentage:(CGFloat)percentage {
|
||||
UIColor *color;
|
||||
|
||||
// Background Color
|
||||
if (percentage >= kMCStop1 && percentage < kMCStop2)
|
||||
color = _firstColor;
|
||||
else if (percentage >= kMCStop2)
|
||||
color = _secondColor;
|
||||
else if (percentage < -kMCStop1 && percentage > -kMCStop2)
|
||||
color = _thirdColor;
|
||||
else if (percentage <= -kMCStop2)
|
||||
color = _fourthColor;
|
||||
else
|
||||
color = self.defaultColor ? self.defaultColor : [UIColor clearColor];
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
- (MCSwipeTableViewCellState)stateWithPercentage:(CGFloat)percentage {
|
||||
MCSwipeTableViewCellState state;
|
||||
|
||||
state = MCSwipeTableViewCellStateNone;
|
||||
|
||||
if (percentage >= kMCStop1 && [self validateState:MCSwipeTableViewCellState1])
|
||||
state = MCSwipeTableViewCellState1;
|
||||
|
||||
if (percentage >= kMCStop2 && [self validateState:MCSwipeTableViewCellState2])
|
||||
state = MCSwipeTableViewCellState2;
|
||||
|
||||
if (percentage <= -kMCStop1 && [self validateState:MCSwipeTableViewCellState3])
|
||||
state = MCSwipeTableViewCellState3;
|
||||
|
||||
if (percentage <= -kMCStop2 && [self validateState:MCSwipeTableViewCellState4])
|
||||
state = MCSwipeTableViewCellState4;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
- (BOOL)validateState:(MCSwipeTableViewCellState)state {
|
||||
BOOL isValid = YES;
|
||||
|
||||
switch (state) {
|
||||
case MCSwipeTableViewCellStateNone: {
|
||||
isValid = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCSwipeTableViewCellState1: {
|
||||
if (!_firstColor && !_firstIconName)
|
||||
isValid = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCSwipeTableViewCellState2: {
|
||||
if (!_secondColor && !_secondIconName)
|
||||
isValid = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCSwipeTableViewCellState3: {
|
||||
if (!_thirdColor && !_thirdIconName)
|
||||
isValid = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCSwipeTableViewCellState4: {
|
||||
if (!_fourthColor && !_fourthIconName)
|
||||
isValid = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
#pragma mark - Movement
|
||||
|
||||
- (void)animateWithOffset:(CGFloat)offset {
|
||||
CGFloat percentage = [self percentageWithOffset:offset relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
|
||||
// Image Name
|
||||
NSString *imageName = [self imageNameWithPercentage:percentage];
|
||||
|
||||
// Image Position
|
||||
if (imageName != nil) {
|
||||
[_slidingImageView setImage:[UIImage imageNamed:imageName]];
|
||||
[_slidingImageView setAlpha:[self imageAlphaWithPercentage:percentage]];
|
||||
[self slideImageWithPercentage:percentage imageName:imageName isDragging:self.shouldAnimatesIcons];
|
||||
}
|
||||
|
||||
// Color
|
||||
UIColor *color = [self colorWithPercentage:percentage];
|
||||
if (color != nil) {
|
||||
[_colorIndicatorView setBackgroundColor:color];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)slideImageWithPercentage:(CGFloat)percentage imageName:(NSString *)imageName isDragging:(BOOL)isDragging {
|
||||
UIImage *slidingImage = [UIImage imageNamed:imageName];
|
||||
CGSize slidingImageSize = slidingImage.size;
|
||||
CGRect slidingImageRect;
|
||||
|
||||
CGPoint position = CGPointZero;
|
||||
|
||||
position.y = CGRectGetHeight(self.bounds) / 2.0;
|
||||
|
||||
if (isDragging) {
|
||||
if (percentage >= 0 && percentage < kMCStop1) {
|
||||
position.x = [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
|
||||
else if (percentage >= kMCStop1) {
|
||||
position.x = [self offsetWithPercentage:percentage - (kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
else if (percentage < 0 && percentage >= -kMCStop1) {
|
||||
position.x = CGRectGetWidth(self.bounds) - [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
|
||||
else if (percentage < -kMCStop1) {
|
||||
position.x = CGRectGetWidth(self.bounds) + [self offsetWithPercentage:percentage + (kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (_direction == MCSwipeTableViewCellDirectionRight) {
|
||||
position.x = [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
else if (_direction == MCSwipeTableViewCellDirectionLeft) {
|
||||
position.x = CGRectGetWidth(self.bounds) - [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
slidingImageRect = CGRectMake(position.x - slidingImageSize.width / 2.0,
|
||||
position.y - slidingImageSize.height / 2.0,
|
||||
slidingImageSize.width,
|
||||
slidingImageSize.height);
|
||||
|
||||
slidingImageRect = CGRectIntegral(slidingImageRect);
|
||||
[_slidingImageView setFrame:slidingImageRect];
|
||||
}
|
||||
|
||||
- (void)moveWithDuration:(NSTimeInterval)duration andDirection:(MCSwipeTableViewCellDirection)direction {
|
||||
CGFloat origin;
|
||||
|
||||
if (direction == MCSwipeTableViewCellDirectionLeft)
|
||||
origin = -CGRectGetWidth(self.bounds);
|
||||
else
|
||||
origin = CGRectGetWidth(self.bounds);
|
||||
|
||||
CGFloat percentage = [self percentageWithOffset:origin relativeToWidth:CGRectGetWidth(self.bounds)];
|
||||
CGRect rect = self.contentView.frame;
|
||||
rect.origin.x = origin;
|
||||
|
||||
// Color
|
||||
UIColor *color = [self colorWithPercentage:_currentPercentage];
|
||||
if (color != nil) {
|
||||
[_colorIndicatorView setBackgroundColor:color];
|
||||
}
|
||||
|
||||
// Image
|
||||
if (_currentImageName != nil) {
|
||||
[_slidingImageView setImage:[UIImage imageNamed:_currentImageName]];
|
||||
}
|
||||
|
||||
[UIView animateWithDuration:duration
|
||||
delay:0.0
|
||||
options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction)
|
||||
animations:^{
|
||||
[self.contentView setFrame:rect];
|
||||
[_slidingImageView setAlpha:0];
|
||||
[self slideImageWithPercentage:percentage imageName:_currentImageName isDragging:self.shouldAnimatesIcons];
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[self notifyDelegate];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)bounceToOrigin {
|
||||
CGFloat bounceDistance = kMCBounceAmplitude * _currentPercentage;
|
||||
|
||||
[UIView animateWithDuration:kMCBounceDuration1
|
||||
delay:0
|
||||
options:(UIViewAnimationOptionCurveEaseOut)
|
||||
animations:^{
|
||||
CGRect frame = self.contentView.frame;
|
||||
frame.origin.x = -bounceDistance;
|
||||
[self.contentView setFrame:frame];
|
||||
[_slidingImageView setAlpha:0.0];
|
||||
[self slideImageWithPercentage:0 imageName:_currentImageName isDragging:NO];
|
||||
|
||||
// Setting back the color to the default
|
||||
_colorIndicatorView.backgroundColor = self.defaultColor;
|
||||
}
|
||||
completion:^(BOOL finished1) {
|
||||
|
||||
[UIView animateWithDuration:kMCBounceDuration2
|
||||
delay:0
|
||||
options:UIViewAnimationOptionCurveEaseIn
|
||||
animations:^{
|
||||
CGRect frame = self.contentView.frame;
|
||||
frame.origin.x = 0;
|
||||
[self.contentView setFrame:frame];
|
||||
|
||||
// Clearing the indicator view
|
||||
_colorIndicatorView.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
completion:^(BOOL finished2) {
|
||||
[self notifyDelegate];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Delegate Notification
|
||||
|
||||
- (void)notifyDelegate {
|
||||
MCSwipeTableViewCellState state = [self stateWithPercentage:_currentPercentage];
|
||||
|
||||
MCSwipeTableViewCellMode mode = self.mode;
|
||||
|
||||
if (mode == MCSwipeTableViewCellModeNone) {
|
||||
switch (state) {
|
||||
case MCSwipeTableViewCellState1: {
|
||||
mode = self.modeForState1;
|
||||
} break;
|
||||
|
||||
case MCSwipeTableViewCellState2: {
|
||||
mode = self.modeForState2;
|
||||
} break;
|
||||
|
||||
case MCSwipeTableViewCellState3: {
|
||||
mode = self.modeForState3;
|
||||
} break;
|
||||
|
||||
case MCSwipeTableViewCellState4: {
|
||||
mode = self.modeForState4;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != MCSwipeTableViewCellStateNone) {
|
||||
if ([_delegate respondsToSelector:@selector(swipeTableViewCell:didEndSwipingSwipingWithState:mode:)]) {
|
||||
[_delegate swipeTableViewCell:self didEndSwipingSwipingWithState:state mode:mode];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
Loading…
Add table
Reference in a new issue