diff --git a/Podfile b/Podfile index 91c1b49..03816ba 100644 --- a/Podfile +++ b/Podfile @@ -6,7 +6,6 @@ platform :ios, '6.0' pod 'AHAlertView', '~>0.0.2' pod 'GVUserDefaults', '~>0.9.0' pod 'SVProgressHUD', '~>0.9' - pod 'ZGPullDragScrollView', '~>0.0.1' target :ProgressTests, :exclusive => true do pod 'GVUserDefaults', '~>0.9.0' diff --git a/Progress.xcodeproj/project.pbxproj b/Progress.xcodeproj/project.pbxproj index 322d048..e26b7b7 100644 --- a/Progress.xcodeproj/project.pbxproj +++ b/Progress.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 040E055516DD864D00E0731D /* UIScrollView+ZGPullDrag.m in Sources */ = {isa = PBXBuildFile; fileRef = 040E055416DD864D00E0731D /* UIScrollView+ZGPullDrag.m */; }; 041C811716DB0DFB0034A3A8 /* GVUserDefaults+Progress.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FD824616DB02910028AF2A /* GVUserDefaults+Progress.m */; }; 041C811B16DB0EAD0034A3A8 /* PPEvenKitManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FD824116DAFB770028AF2A /* PPEvenKitManager.m */; }; 041C811E16DB0F080034A3A8 /* PPEvenKitManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 041C811D16DB0F080034A3A8 /* PPEvenKitManagerTest.m */; }; @@ -50,6 +51,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 040E055316DD864D00E0731D /* UIScrollView+ZGPullDrag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+ZGPullDrag.h"; sourceTree = ""; }; + 040E055416DD864D00E0731D /* UIScrollView+ZGPullDrag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+ZGPullDrag.m"; sourceTree = ""; }; 041C811C16DB0F080034A3A8 /* PPEvenKitManagerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPEvenKitManagerTest.h; sourceTree = ""; }; 041C811D16DB0F080034A3A8 /* PPEvenKitManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPEvenKitManagerTest.m; sourceTree = ""; }; 04386A0B16908C4C0058C876 /* Progress.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Progress.entitlements; sourceTree = ""; }; @@ -158,6 +161,8 @@ 04BDDECA16902D0900D04A9E /* Progress */ = { isa = PBXGroup; children = ( + 040E055316DD864D00E0731D /* UIScrollView+ZGPullDrag.h */, + 040E055416DD864D00E0731D /* UIScrollView+ZGPullDrag.m */, 048D437016DBC4E000A40CB1 /* ReminderItemCell.h */, 048D437116DBC4E000A40CB1 /* ReminderItemCell.m */, 048D433E16DB9D5300A40CB1 /* PPRemindersViewController.h */, @@ -365,6 +370,7 @@ 04FD824716DB02910028AF2A /* GVUserDefaults+Progress.m in Sources */, 048D434016DB9D5400A40CB1 /* PPRemindersViewController.m in Sources */, 048D437216DBC4E000A40CB1 /* ReminderItemCell.m in Sources */, + 040E055516DD864D00E0731D /* UIScrollView+ZGPullDrag.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Progress/PPRemindersViewController.m b/Progress/PPRemindersViewController.m index 4c19c8c..57dfad5 100644 --- a/Progress/PPRemindersViewController.m +++ b/Progress/PPRemindersViewController.m @@ -9,7 +9,7 @@ #import "PPRemindersViewController.h" #import "PPEvenKitManager.h" #import -#import +#import "UIScrollView+ZGPullDrag.h" #import #import #import "ReminderItemCell.h" @@ -17,6 +17,8 @@ @interface PPRemindersViewController () @property (strong, nonatomic) IBOutlet UIView *pullDownView; @property (nonatomic, strong) UITableViewCell *placeHolderCell; +@property (nonatomic, strong) UITableViewCell *editingCell; +@property (nonatomic) BOOL isEdingAReminder; @property (nonatomic) NSArray *remindersDatasource; @end @@ -24,10 +26,13 @@ static NSString *CellIdentifier = @"ReminderCell"; + + - (void)viewDidLoad { [super viewDidLoad]; + self.isEdingAReminder = NO; self.clearsSelectionOnViewWillAppear = NO; self.navigationController.navigationBarHidden = YES; @@ -72,35 +77,35 @@ static NSString *CellIdentifier = @"ReminderCell"; if (!_placeHolderCell) { _placeHolderCell = [[UITableViewCell alloc] initWithFrame:CGRectZero]; _placeHolderCell.frame = CGRectMake(0, 0, self.view.frame.size.width, self.tableView.rowHeight); - UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 29, 300, 21)]; - textField.borderStyle = UITextBorderStyleNone; - textField.font = [UIFont systemFontOfSize:17.0]; - textField.tag = 1; - [_placeHolderCell addSubview:textField]; } return _placeHolderCell; } -- (void)pullView:(UIView *)pullView hangForCompletionBlock:(void (^)())completed{ - [[self.placeHolderCell viewWithTag:1] becomeFirstResponder]; + +- (void)userPullOrDragStoppedWithPullView:(UIView *)pullView dragView:(UIView *)dragView{ + NSLog(@"Stopped"); } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.remindersDatasource.count; + return self.isEdingAReminder ? self.remindersDatasource.count+1 : self.remindersDatasource.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - ReminderItemCell *cell = [[ReminderItemCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; - EKReminder *reminder = [self.remindersDatasource objectAtIndex:indexPath.row]; - cell.delegate = self; - cell.textLabel.text = reminder.title; - cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", indexPath.row]; - cell.accessoryType = reminder.completed ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; - return cell; + if (self.isEdingAReminder && indexPath.row == 0) { + return self.editingCell; + } else { + ReminderItemCell *cell = [[ReminderItemCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; + EKReminder *reminder = [self.remindersDatasource objectAtIndex:self.isEdingAReminder?indexPath.row-1:indexPath.row]; + cell.delegate = self; + cell.textLabel.text = reminder.title; + cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", indexPath.row]; + cell.accessoryType = reminder.completed ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; + return cell; + } } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ diff --git a/Progress/ReminderItemCell.m b/Progress/ReminderItemCell.m index 1987c9f..fd18b1e 100644 --- a/Progress/ReminderItemCell.m +++ b/Progress/ReminderItemCell.m @@ -29,11 +29,11 @@ UIImageView *checkMarkView = [[UIImageView alloc] initWithFrame:checkMarkOriginFrame]; checkMarkView.backgroundColor = [UIColor greenColor]; - checkMarkView.highlightedImage = nil; + checkMarkView.alpha = 0; checkMarkView.tag = 1; UIImageView *deleteMarkView = [[UIImageView alloc] initWithFrame:deleteMarkOriginFrame]; deleteMarkView.backgroundColor = [UIColor redColor]; - deleteMarkView.highlightedImage = nil; + deleteMarkView.alpha = 0; deleteMarkView.tag = 2; [self insertSubview:checkMarkView atIndex:0]; [self insertSubview:deleteMarkView atIndex:0]; @@ -73,7 +73,9 @@ if (gesture.state == UIGestureRecognizerStateBegan) { self.originalCenter = self.center; checkMarkView.frame = checkMarkOriginFrame; + checkMarkView.alpha = 0; deleteMarkView.frame = deleteMarkOriginFrame; + deleteMarkView.alpha = 0; } else { CGPoint translation = [gesture translationInView:self]; CGFloat xOffset = translation.x; @@ -81,7 +83,9 @@ self.center = CGPointMake(self.originalCenter.x+xOffset, self.originalCenter.y); if (xOffset>-kDefaultEdageXOffset && xOffsetkDefaultEdageXOffset) { diff --git a/Progress/UIScrollView+ZGPullDrag.h b/Progress/UIScrollView+ZGPullDrag.h new file mode 100644 index 0000000..c4eb27a --- /dev/null +++ b/Progress/UIScrollView+ZGPullDrag.h @@ -0,0 +1,32 @@ +// +// UIScrollView+ZGPullDrag.h +// ZGPullDragScrollView +// +// Created by Kyle Fang on 2/26/13. +// Copyright (c) 2013 Kyle Fang. All rights reserved. +// + +#import + +@protocol ZGPullDragViewDelegate +@optional + +//Push Down +- (void)pullView:(UIView *)pullView Show:(CGFloat )shownPixels ofTotal:(CGFloat )totalPixels; +- (void)pullView:(UIView *)pullView hangForCompletionBlock:(void (^)())completed; + +//Drag Up +- (void)dragView:(UIView *)dragView Show:(CGFloat )showPixels ofTotal:(CGFloat )totalPixels; +- (void)dragView:(UIView *)dragView hangForCompletionBlock:(void (^)())completed; + +//User Pull or Drag stopped + +- (void)userPullOrDragStoppedWithPullView:(UIView *)pullView dragView:(UIView *)dragView; + +@end + +@interface UIScrollView (ZGPullDrag) +- (void)addZGPullView:(UIView *)pullView; +- (void)addZGDragView:(UIView *)dragView; +@property (nonatomic) id pullDragDelegate; +@end diff --git a/Progress/UIScrollView+ZGPullDrag.m b/Progress/UIScrollView+ZGPullDrag.m new file mode 100644 index 0000000..a2f6150 --- /dev/null +++ b/Progress/UIScrollView+ZGPullDrag.m @@ -0,0 +1,203 @@ +// +// UIScrollView+ZGPullDrag.m +// ZGPullDragScrollView +// +// Created by Kyle Fang on 2/26/13. +// Copyright (c) 2013 Kyle Fang. All rights reserved. +// + +#import "UIScrollView+ZGPullDrag.h" +#import + +static char UIScrollViewZGPullDragViewDelegate; +static char UIScrollViewZGPullDragViewObserving; +static char UIScrollViewZGPullView; +static char UIScrollViewZGDragView; +static char UIScrollViewWasDragging; + +@interface UIScrollView (ZGPullDragPropertyCategory) +@property (nonatomic) BOOL isObserving; +@property (nonatomic, assign) UIView *pullView; +@property (nonatomic, assign) UIView *dragView; +@property (nonatomic) BOOL wasDragging; +@end + +@implementation UIScrollView (ZGPullDragPropertyCategory) + +- (void)setIsObserving:(BOOL)isObserving { + if (self.isObserving == YES && isObserving == NO) { + @try { + [self removeObserver:self forKeyPath:@"contentOffset"]; + } + @catch (NSException *exception) { + //It's not observing + } + } else if (self.isObserving == NO && isObserving == YES) { + [self addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; + } + + [self willChangeValueForKey:@"isObserving"]; + objc_setAssociatedObject(self, &UIScrollViewZGPullDragViewObserving, + [NSNumber numberWithBool:isObserving], + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self didChangeValueForKey:@"isObserving"]; +} + +- (BOOL)isObserving { + NSNumber *number = objc_getAssociatedObject(self, &UIScrollViewZGPullDragViewObserving); + if (number == nil) { + return NO; + } else { + return [number boolValue]; + } +} + +- (void)setPullView:(UIView *)pullView{ + [self willChangeValueForKey:@"pullView"]; + objc_setAssociatedObject(self, &UIScrollViewZGPullView, pullView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self didChangeValueForKey:@"pullView"]; +} + +- (UIView *)pullView{ + return objc_getAssociatedObject(self, &UIScrollViewZGPullView); +} + +- (void)setDragView:(UIView *)dragView{ + [self willChangeValueForKey:@"dragView"]; + objc_setAssociatedObject(self, &UIScrollViewZGDragView, dragView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self didChangeValueForKey:@"dragView"]; +} + +- (UIView *)dragView{ + return objc_getAssociatedObject(self, &UIScrollViewZGDragView); +} + +- (void)setWasDragging:(BOOL)wasDragging{ + [self willChangeValueForKey:@"wasDragging"]; + objc_setAssociatedObject(self, &UIScrollViewWasDragging, [NSNumber numberWithBool:wasDragging], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self didChangeValueForKey:@"wasDragging"]; +} + +- (BOOL)wasDragging{ + NSNumber *number = objc_getAssociatedObject(self, &UIScrollViewWasDragging); + if (number == nil) { + return NO; + } else { + return [number isEqualToNumber:@YES]; + } +} + +@end + + +@implementation UIScrollView (ZGPullDrag) +@dynamic pullDragDelegate; + +- (void)setPullDragDelegate:(id)pullDragDelegate{ + [self willChangeValueForKey:@"pullDragDelegate"]; + objc_setAssociatedObject(self, &UIScrollViewZGPullDragViewDelegate, pullDragDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self didChangeValueForKey:@"pullDragDelegate"]; +} + +- (id)pullDragDelegate{ + return objc_getAssociatedObject(self, &UIScrollViewZGPullDragViewDelegate); +} + +- (void)addZGPullView:(UIView *)pullView{ + if (self.pullView != pullView) { + [self.pullView removeFromSuperview]; + } + pullView.frame = CGRectOffset(pullView.frame, -pullView.frame.origin.x, -pullView.frame.origin.y-pullView.frame.size.height); + [self addSubview:pullView]; + self.pullView = pullView; + self.isObserving = YES; +} + +- (void)addZGDragView:(UIView *)dragView{ + if (self.dragView != dragView) { + [self.dragView removeFromSuperview]; + } + [self layoutIfNeeded]; + CGFloat originY = MAX(self.frame.size.height, self.contentSize.height); + dragView.frame = CGRectOffset(dragView.frame, -dragView.frame.origin.x, -dragView.frame.origin.y+originY); + [self addSubview:dragView]; + self.dragView = dragView; + self.isObserving = YES; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ + if ([keyPath isEqualToString:@"contentOffset"]) { + [self scrollViewDidScroll:[[change valueForKey:NSKeyValueChangeNewKey] CGPointValue]]; + } +} + +- (void)scrollViewDidScroll:(CGPoint )contentOffset { + CGFloat yOffset = contentOffset.y; + if (yOffset<0) { + [self pullViewHandler:-yOffset]; + } else if (self.dragView.frame.origin.y == self.frame.size.height) { + [self dragViewHandler:yOffset]; + } else if (self.dragView.frame.origin.y == self.contentSize.height && yOffset > self.dragView.frame.origin.y - self.frame.size.height) { + [self dragViewHandler:yOffset-(self.dragView.frame.origin.y - self.frame.size.height)]; + } + if (self.wasDragging && !self.isDragging) { + if ([self.pullDragDelegate respondsToSelector:@selector(userPullOrDragStoppedWithPullView:dragView:)]) { + [self.pullDragDelegate userPullOrDragStoppedWithPullView:self.pullView dragView:self.dragView]; + } + } + self.wasDragging = self.isDragging; +} + +- (void)pullViewHandler:(CGFloat )visiblePixels{ + if ([self.pullDragDelegate respondsToSelector:@selector(pullView:Show:ofTotal:)]) { + [self.pullDragDelegate pullView:self.pullView Show:visiblePixels ofTotal:self.pullView.frame.size.height]; + } + if (visiblePixels>self.pullView.frame.size.height && !self.isDragging && [self.pullDragDelegate respondsToSelector:@selector(pullView:hangForCompletionBlock:)]) { + [UIView animateWithDuration:0.1 + animations:^{ + self.contentInset = UIEdgeInsetsMake(self.pullView.frame.size.height, 0, 0, 0); + } completion:^(BOOL finished) { + [self.pullDragDelegate pullView:self.pullView hangForCompletionBlock:^{ + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [UIView animateWithDuration:0.2 animations:^{ + self.contentInset = UIEdgeInsetsZero; + }]; + }]; + }]; + }]; + } +} + + +- (void)dragViewHandler:(CGFloat )visiblePixels{ + if ([self.pullDragDelegate respondsToSelector:@selector(dragView:Show:ofTotal:)]) { + [self.pullDragDelegate dragView:self.dragView Show:visiblePixels ofTotal:self.dragView.frame.size.height]; + } + if (visiblePixels>self.dragView.frame.size.height && !self.isDragging && [self.pullDragDelegate respondsToSelector:@selector(dragView:hangForCompletionBlock:)]) { + [UIView animateWithDuration:0.1 + animations:^{ + if (self.dragView.frame.origin.y == self.frame.size.height) { + self.contentInset = UIEdgeInsetsMake(0, 0, self.dragView.frame.size.height + self.frame.size.height - self.contentSize.height, 0); + } else { + self.contentInset = UIEdgeInsetsMake(0, 0, self.dragView.frame.size.height, 0); + } + } completion:^(BOOL finished) { + + [self.pullDragDelegate dragView:self.dragView hangForCompletionBlock:^{ + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [UIView animateWithDuration:0.2 animations:^{ + self.contentInset = UIEdgeInsetsZero; + }]; + }]; + }]; + }]; + } +} + +- (void)dealloc{ + if (self.isObserving) { + self.isObserving = NO; + } +} + +@end diff --git a/Progress/en.lproj/Progress.storyboard b/Progress/en.lproj/Progress.storyboard index 66deada..f9a9181 100644 --- a/Progress/en.lproj/Progress.storyboard +++ b/Progress/en.lproj/Progress.storyboard @@ -13,9 +13,32 @@ - + + + + + + + + + + + + + + + + + + + + + + + +