diff options
author | Marino Faggiana <m.faggiana@twsweb.it> | 2018-11-12 13:32:13 +0300 |
---|---|---|
committer | Marino Faggiana <marinofaggiana@MacBook-Pro-di-Marino.local> | 2018-11-12 13:32:13 +0300 |
commit | fe44acc499e4c0db43e26af70e5c274f83bd7695 (patch) | |
tree | 0c81d0f5409e1d326abb0a51d6467c9a6333c023 /Libraries external | |
parent | 5905b007c42cf594c644b643ad7df9cf40c78286 (diff) |
update project
Diffstat (limited to 'Libraries external')
-rwxr-xr-x | Libraries external/MGSwipeTableCell/MGSwipeButton.h | 51 | ||||
-rwxr-xr-x | Libraries external/MGSwipeTableCell/MGSwipeButton.m | 159 | ||||
-rwxr-xr-x | Libraries external/MGSwipeTableCell/MGSwipeTableCell.h | 276 | ||||
-rwxr-xr-x | Libraries external/MGSwipeTableCell/MGSwipeTableCell.m | 1389 |
4 files changed, 0 insertions, 1875 deletions
diff --git a/Libraries external/MGSwipeTableCell/MGSwipeButton.h b/Libraries external/MGSwipeTableCell/MGSwipeButton.h deleted file mode 100755 index 1da612637..000000000 --- a/Libraries external/MGSwipeTableCell/MGSwipeButton.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * MGSwipeTableCell is licensed under MIT license. See LICENSE.md file for more information. - * Copyright (c) 2016 Imanol Fernandez @MortimerGoro - */ - -#import <UIKit/UIKit.h> - - -@class MGSwipeTableCell; - -/** - * This is a convenience class to create MGSwipeTableCell buttons - * Using this class is optional because MGSwipeTableCell is button agnostic and can use any UIView for that purpose - * Anyway, it's recommended that you use this class because is totally tested and easy to use ;) - */ -@interface MGSwipeButton : UIButton - -/** - * Convenience block callback for developers lazy to implement the MGSwipeTableCellDelegate. - * @return Return YES to autohide the swipe view - */ -typedef BOOL(^ MGSwipeButtonCallback)(MGSwipeTableCell * _Nonnull cell); -@property (nonatomic, strong, nullable) MGSwipeButtonCallback callback; - -/** A width for the expanded buttons. Defaults to 0, which means sizeToFit will be called. */ -@property (nonatomic, assign) CGFloat buttonWidth; - -/** - * Convenience static constructors - */ -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title backgroundColor:(nullable UIColor *) color; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title backgroundColor:(nullable UIColor *) color padding:(NSInteger) padding; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title backgroundColor:(nullable UIColor *) color insets:(UIEdgeInsets) insets; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title backgroundColor:(nullable UIColor *) color callback:(nullable MGSwipeButtonCallback) callback; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title backgroundColor:(nullable UIColor *) color padding:(NSInteger) padding callback:(nullable MGSwipeButtonCallback) callback; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title backgroundColor:(nullable UIColor *) color insets:(UIEdgeInsets) insets callback:(nullable MGSwipeButtonCallback) callback; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title icon:(nullable UIImage*) icon backgroundColor:(nullable UIColor *) color; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title icon:(nullable UIImage*) icon backgroundColor:(nullable UIColor *) color padding:(NSInteger) padding; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title icon:(nullable UIImage*) icon backgroundColor:(nullable UIColor *) color insets:(UIEdgeInsets) insets; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title icon:(nullable UIImage*) icon backgroundColor:(nullable UIColor *) color callback:(nullable MGSwipeButtonCallback) callback; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title icon:(nullable UIImage*) icon backgroundColor:(nullable UIColor *) color padding:(NSInteger) padding callback:(nullable MGSwipeButtonCallback) callback; -+(nonnull instancetype) buttonWithTitle:(nonnull NSString *) title icon:(nullable UIImage*) icon backgroundColor:(nullable UIColor *) color insets:(UIEdgeInsets) insets callback:(nullable MGSwipeButtonCallback) callback; - --(void) setPadding:(CGFloat) padding; --(void) setEdgeInsets:(UIEdgeInsets)insets; --(void) centerIconOverText; --(void) centerIconOverTextWithSpacing: (CGFloat) spacing; --(void) iconTintColor:(nullable UIColor *)tintColor; - - -@end diff --git a/Libraries external/MGSwipeTableCell/MGSwipeButton.m b/Libraries external/MGSwipeTableCell/MGSwipeButton.m deleted file mode 100755 index 1c005452a..000000000 --- a/Libraries external/MGSwipeTableCell/MGSwipeButton.m +++ /dev/null @@ -1,159 +0,0 @@ -/* - * MGSwipeTableCell is licensed under MIT license. See LICENSE.md file for more information. - * Copyright (c) 2016 Imanol Fernandez @MortimerGoro - */ - -#import "MGSwipeButton.h" - -@class MGSwipeTableCell; - -@implementation MGSwipeButton - -+(instancetype) buttonWithTitle:(NSString *) title backgroundColor:(UIColor *) color -{ - return [self buttonWithTitle:title icon:nil backgroundColor:color]; -} - -+(instancetype) buttonWithTitle:(NSString *) title backgroundColor:(UIColor *) color padding:(NSInteger) padding -{ - return [self buttonWithTitle:title icon:nil backgroundColor:color insets:UIEdgeInsetsMake(0, padding, 0, padding)]; -} - -+(instancetype) buttonWithTitle:(NSString *) title backgroundColor:(UIColor *) color insets:(UIEdgeInsets) insets -{ - return [self buttonWithTitle:title icon:nil backgroundColor:color insets:insets]; -} - -+(instancetype) buttonWithTitle:(NSString *) title backgroundColor:(UIColor *) color callback:(MGSwipeButtonCallback) callback -{ - return [self buttonWithTitle:title icon:nil backgroundColor:color callback:callback]; -} - -+(instancetype) buttonWithTitle:(NSString *) title backgroundColor:(UIColor *) color padding:(NSInteger) padding callback:(MGSwipeButtonCallback) callback -{ - return [self buttonWithTitle:title icon:nil backgroundColor:color insets:UIEdgeInsetsMake(0, padding, 0, padding) callback:callback]; -} - -+(instancetype) buttonWithTitle:(NSString *) title backgroundColor:(UIColor *) color insets:(UIEdgeInsets) insets callback:(MGSwipeButtonCallback) callback -{ - return [self buttonWithTitle:title icon:nil backgroundColor:color insets:insets callback:callback]; -} - -+(instancetype) buttonWithTitle:(NSString *) title icon:(UIImage*) icon backgroundColor:(UIColor *) color -{ - return [self buttonWithTitle:title icon:icon backgroundColor:color callback:nil]; -} - -+(instancetype) buttonWithTitle:(NSString *) title icon:(UIImage*) icon backgroundColor:(UIColor *) color padding:(NSInteger) padding -{ - return [self buttonWithTitle:title icon:icon backgroundColor:color insets:UIEdgeInsetsMake(0, padding, 0, padding) callback:nil]; -} - -+(instancetype) buttonWithTitle:(NSString *) title icon:(UIImage*) icon backgroundColor:(UIColor *) color insets:(UIEdgeInsets) insets -{ - return [self buttonWithTitle:title icon:icon backgroundColor:color insets:insets callback:nil]; -} - -+(instancetype) buttonWithTitle:(NSString *) title icon:(UIImage*) icon backgroundColor:(UIColor *) color callback:(MGSwipeButtonCallback) callback -{ - return [self buttonWithTitle:title icon:icon backgroundColor:color padding:10 callback:callback]; -} - -+(instancetype) buttonWithTitle:(NSString *) title icon:(UIImage*) icon backgroundColor:(UIColor *) color padding:(NSInteger) padding callback:(MGSwipeButtonCallback) callback -{ - return [self buttonWithTitle:title icon:icon backgroundColor:color insets:UIEdgeInsetsMake(0, padding, 0, padding) callback:callback]; -} - -+(instancetype) buttonWithTitle:(NSString *) title icon:(UIImage*) icon backgroundColor:(UIColor *) color insets:(UIEdgeInsets) insets callback:(MGSwipeButtonCallback) callback -{ - MGSwipeButton * button = [self buttonWithType:UIButtonTypeCustom]; - button.backgroundColor = color; - button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; - button.titleLabel.textAlignment = NSTextAlignmentCenter; - [button setTitle:title forState:UIControlStateNormal]; - [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - [button setImage:icon forState:UIControlStateNormal]; - button.callback = callback; - [button setEdgeInsets:insets]; - return button; -} - --(BOOL) callMGSwipeConvenienceCallback: (MGSwipeTableCell *) sender -{ - if (_callback) { - return _callback(sender); - } - return NO; -} - --(void) centerIconOverText -{ - [self centerIconOverTextWithSpacing: 3.0]; -} - --(void) centerIconOverTextWithSpacing: (CGFloat) spacing { - CGSize size = self.imageView.image.size; - - if ([UIDevice currentDevice].systemVersion.floatValue >= 9.0 && [UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) { - self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - 0.0, - -(size.height + spacing), - -size.width); - size = [self.titleLabel.text sizeWithAttributes:@{ NSFontAttributeName: self.titleLabel.font }]; - self.imageEdgeInsets = UIEdgeInsetsMake(-(size.height + spacing), - -size.width, - 0.0, - 0.0); - } - else - { - self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - -size.width, - -(size.height + spacing), - 0.0); - size = [self.titleLabel.text sizeWithAttributes:@{ NSFontAttributeName: self.titleLabel.font }]; - self.imageEdgeInsets = UIEdgeInsetsMake(-(size.height + spacing), - 0.0, - 0.0, - -size.width); - } -} - --(void) setPadding:(CGFloat) padding -{ - self.contentEdgeInsets = UIEdgeInsetsMake(0, padding, 0, padding); - [self sizeToFit]; -} - -- (void)setButtonWidth:(CGFloat)buttonWidth -{ - _buttonWidth = buttonWidth; - if (_buttonWidth > 0) - { - CGRect frame = self.frame; - frame.size.width = _buttonWidth; - self.frame = frame; - } - else - { - [self sizeToFit]; - } -} - --(void) setEdgeInsets:(UIEdgeInsets)insets -{ - self.contentEdgeInsets = insets; - [self sizeToFit]; -} - --(void) iconTintColor:(UIColor *)tintColor -{ - UIImage *currentIcon = self.imageView.image; - if (currentIcon.renderingMode != UIImageRenderingModeAlwaysTemplate) { - currentIcon = [currentIcon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - [self setImage:currentIcon forState:UIControlStateNormal]; - } - self.tintColor = tintColor; -} - -@end diff --git a/Libraries external/MGSwipeTableCell/MGSwipeTableCell.h b/Libraries external/MGSwipeTableCell/MGSwipeTableCell.h deleted file mode 100755 index 1a9a3889d..000000000 --- a/Libraries external/MGSwipeTableCell/MGSwipeTableCell.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * MGSwipeTableCell is licensed under MIT license. See LICENSE.md file for more information. - * Copyright (c) 2016 Imanol Fernandez @MortimerGoro - */ - -#import <UIKit/UIKit.h> -#import "MGSwipeButton.h" - - -/** Transition types */ -typedef NS_ENUM(NSInteger, MGSwipeTransition) { - MGSwipeTransitionBorder = 0, - MGSwipeTransitionStatic, - MGSwipeTransitionDrag, - MGSwipeTransitionClipCenter, - MGSwipeTransitionRotate3D -}; - -/** Compatibility with older versions */ -#define MGSwipeTransition3D MGSwipeTransitionRotate3D -#define MGSwipeStateSwippingLeftToRight MGSwipeStateSwipingLeftToRight -#define MGSwipeStateSwippingRightToLeft MGSwipeStateSwipingRightToLeft - -/** Swipe directions */ -typedef NS_ENUM(NSInteger, MGSwipeDirection) { - MGSwipeDirectionLeftToRight = 0, - MGSwipeDirectionRightToLeft -}; - -/** Swipe state */ -typedef NS_ENUM(NSInteger, MGSwipeState) { - MGSwipeStateNone = 0, - MGSwipeStateSwipingLeftToRight, - MGSwipeStateSwipingRightToLeft, - MGSwipeStateExpandingLeftToRight, - MGSwipeStateExpandingRightToLeft, -}; - -/** Swipe state */ -typedef NS_ENUM(NSInteger, MGSwipeExpansionLayout) { - MGSwipeExpansionLayoutBorder = 0, - MGSwipeExpansionLayoutCenter, - MGSwipeExpansionLayoutNone -}; - -/** Swipe Easing Function */ -typedef NS_ENUM(NSInteger, MGSwipeEasingFunction) { - MGSwipeEasingFunctionLinear = 0, - MGSwipeEasingFunctionQuadIn, - MGSwipeEasingFunctionQuadOut, - MGSwipeEasingFunctionQuadInOut, - MGSwipeEasingFunctionCubicIn, - MGSwipeEasingFunctionCubicOut, - MGSwipeEasingFunctionCubicInOut, - MGSwipeEasingFunctionBounceIn, - MGSwipeEasingFunctionBounceOut, - MGSwipeEasingFunctionBounceInOut -}; - -/** - * Swipe animation settings - **/ -@interface MGSwipeAnimation : NSObject -/** Animation duration in seconds. Default value 0.3 */ -@property (nonatomic, assign) CGFloat duration; -/** Animation easing function. Default value EaseOutBounce */ -@property (nonatomic, assign) MGSwipeEasingFunction easingFunction; -/** Override this method to implement custom easing functions */ --(CGFloat) value:(CGFloat) elapsed duration:(CGFloat) duration from:(CGFloat) from to:(CGFloat) to; - -@end - -/** - * Swipe settings - **/ -@interface MGSwipeSettings: NSObject -/** Transition used while swiping buttons */ -@property (nonatomic, assign) MGSwipeTransition transition; -/** Size proportional threshold to hide/keep the buttons when the user ends swiping. Default value 0.5 */ -@property (nonatomic, assign) CGFloat threshold; -/** Optional offset to change the swipe buttons position. Relative to the cell border position. Default value: 0 - ** For example it can be used to avoid cropped buttons when sectionIndexTitlesForTableView is used in the UITableView - **/ -@property (nonatomic, assign) CGFloat offset; -/** Top margin of the buttons relative to the contentView */ -@property (nonatomic, assign) CGFloat topMargin; -/** Bottom margin of the buttons relative to the contentView */ -@property (nonatomic, assign) CGFloat bottomMargin; -/** Distance between the buttons. Default value : 0 */ -@property (nonatomic, assign) CGFloat buttonsDistance; - -/** Animation settings when the swipe buttons are shown */ -@property (nonatomic, strong, nonnull) MGSwipeAnimation * showAnimation; -/** Animation settings when the swipe buttons are hided */ -@property (nonatomic, strong, nonnull) MGSwipeAnimation * hideAnimation; -/** Animation settings when the cell is stretched from the swipe buttons */ -@property (nonatomic, strong, nonnull) MGSwipeAnimation * stretchAnimation; - -/** Property to read or change swipe animation durations. Default value 0.3 */ -@property (nonatomic, assign) CGFloat animationDuration DEPRECATED_ATTRIBUTE; - -/** If true the buttons are kept swiped when the threshold is reached and the user ends the gesture - * If false, the buttons are always hidden when the user ends the swipe gesture - */ -@property (nonatomic, assign) BOOL keepButtonsSwiped; - -/** If true the table cell is not swiped, just the buttons **/ -@property (nonatomic, assign) BOOL onlySwipeButtons; - -/** If NO the swipe bounces will be disabled, the swipe motion will stop right after the button */ -@property (nonatomic, assign) BOOL enableSwipeBounces; - -/** Coefficient applied to cell movement in bounce zone. Set to value between 0.0 and 1.0 - to make the cell 'resist' swiping after buttons are revealed. Default is 1.0 */ -@property (nonatomic, assign) CGFloat swipeBounceRate; - -@end - - -/** - * Expansion settings to make expandable buttons - * Swipe button are not expandable by default - **/ -@interface MGSwipeExpansionSettings: NSObject -/** index of the expandable button (in the left or right buttons arrays) */ -@property (nonatomic, assign) NSInteger buttonIndex; -/** if true the button fills the cell on trigger, else it bounces back to its initial position */ -@property (nonatomic, assign) BOOL fillOnTrigger; -/** Size proportional threshold to trigger the expansion button. Default value 1.5 */ -@property (nonatomic, assign) CGFloat threshold; -/** Optional expansion color. Expanded button's background color is used by default **/ -@property (nonatomic, strong, nullable) UIColor * expansionColor; -/** Defines the layout of the expanded button **/ -@property (nonatomic, assign) MGSwipeExpansionLayout expansionLayout; -/** Animation settings when the expansion is triggered **/ -@property (nonatomic, strong, nonnull) MGSwipeAnimation * triggerAnimation; - -/** Property to read or change expansion animation durations. Default value 0.2 - * The target animation is the change of a button from normal state to expanded state - */ -@property (nonatomic, assign) CGFloat animationDuration; -@end - - -/** helper forward declaration */ -@class MGSwipeTableCell; - -/** - * Optional delegate to configure swipe buttons or to receive triggered actions. - * Buttons can be configured inline when the cell is created instead of using this delegate, - * but using the delegate improves memory usage because buttons are only created in demand - */ -@protocol MGSwipeTableCellDelegate <NSObject> - -@optional -/** - * Delegate method to enable/disable swipe gestures - * @return YES if swipe is allowed - **/ --(BOOL) swipeTableCell:(nonnull MGSwipeTableCell*) cell canSwipe:(MGSwipeDirection) direction fromPoint:(CGPoint) point; --(BOOL) swipeTableCell:(nonnull MGSwipeTableCell*) cell canSwipe:(MGSwipeDirection) direction DEPRECATED_ATTRIBUTE; //backwards compatibility - -/** - * Delegate method invoked when the current swipe state changes - @param state the current Swipe State - @param gestureIsActive YES if the user swipe gesture is active. No if the uses has already ended the gesture - **/ --(void) swipeTableCell:(nonnull MGSwipeTableCell*) cell didChangeSwipeState:(MGSwipeState) state gestureIsActive:(BOOL) gestureIsActive; - -/** - * Called when the user clicks a swipe button or when a expandable button is automatically triggered - * @return YES to autohide the current swipe buttons - **/ --(BOOL) swipeTableCell:(nonnull MGSwipeTableCell*) cell tappedButtonAtIndex:(NSInteger) index direction:(MGSwipeDirection)direction fromExpansion:(BOOL) fromExpansion; -/** - * Delegate method to setup the swipe buttons and swipe/expansion settings - * Buttons can be any kind of UIView but it's recommended to use the convenience MGSwipeButton class - * Setting up buttons with this delegate instead of using cell properties improves memory usage because buttons are only created in demand - * @param cell the UITableViewCell to configure. You can get the indexPath using [tableView indexPathForCell:cell] - * @param direction The swipe direction (left to right or right to left) - * @param swipeSettings instance to configure the swipe transition and setting (optional) - * @param expansionSettings instance to configure button expansions (optional) - * @return Buttons array - **/ --(nullable NSArray<UIView*>*) swipeTableCell:(nonnull MGSwipeTableCell*) cell swipeButtonsForDirection:(MGSwipeDirection)direction - swipeSettings:(nonnull MGSwipeSettings*) swipeSettings expansionSettings:(nonnull MGSwipeExpansionSettings*) expansionSettings; - -/** - * Called when the user taps on a swiped cell - * @return YES to autohide the current swipe buttons - **/ --(BOOL) swipeTableCell:(nonnull MGSwipeTableCell *)cell shouldHideSwipeOnTap:(CGPoint) point; - -/** - * Called when the cell will begin swiping - * Useful to make cell changes that only are shown after the cell is swiped open - **/ --(void) swipeTableCellWillBeginSwiping:(nonnull MGSwipeTableCell *) cell; - -/** - * Called when the cell will end swiping - **/ --(void) swipeTableCellWillEndSwiping:(nonnull MGSwipeTableCell *) cell; - -@end - - -/** - * Swipe Cell class - * To implement swipe cells you have to override from this class - * You can create the cells programmatically, using xibs or storyboards - */ -@interface MGSwipeTableCell : UITableViewCell - -/** optional delegate (not retained) */ -@property (nonatomic, weak, nullable) id<MGSwipeTableCellDelegate> delegate; - -/** optional to use contentView alternative. Use this property instead of contentView to support animated views while swiping */ -@property (nonatomic, strong, readonly, nonnull) UIView * swipeContentView; - -/** - * Left and right swipe buttons and its settings. - * Buttons can be any kind of UIView but it's recommended to use the convenience MGSwipeButton class - */ -@property (nonatomic, copy, nonnull) NSArray<UIView*> * leftButtons; -@property (nonatomic, copy, nonnull) NSArray<UIView*> * rightButtons; -@property (nonatomic, strong, nonnull) MGSwipeSettings * leftSwipeSettings; -@property (nonatomic, strong, nonnull) MGSwipeSettings * rightSwipeSettings; - -/** Optional settings to allow expandable buttons */ -@property (nonatomic, strong, nonnull) MGSwipeExpansionSettings * leftExpansion; -@property (nonatomic, strong, nonnull) MGSwipeExpansionSettings * rightExpansion; - -/** Readonly property to fetch the current swipe state */ -@property (nonatomic, readonly) MGSwipeState swipeState; -/** Readonly property to check if the user swipe gesture is currently active */ -@property (nonatomic, readonly) BOOL isSwipeGestureActive; - -// default is NO. Controls whether multiple cells can be swiped simultaneously -@property (nonatomic) BOOL allowsMultipleSwipe; -// default is NO. Controls whether buttons with different width are allowed. Buttons are resized to have the same size by default. -@property (nonatomic) BOOL allowsButtonsWithDifferentWidth; -//default is YES. Controls whether swipe gesture is allowed when the touch starts into the swiped buttons -@property (nonatomic) BOOL allowsSwipeWhenTappingButtons; -//default is YES. Controls whether swipe gesture is allowed in opposite directions. NO value disables swiping in opposite direction once started in one direction -@property (nonatomic) BOOL allowsOppositeSwipe; -// default is NO. Controls whether the cell selection/highlight status is preserved when expansion occurs -@property (nonatomic) BOOL preservesSelectionStatus; -/* default is NO. Controls whether dismissing a swiped cell when tapping outside of the cell generates a real touch event on the other cell. - Default behaviour is the same as the Mail app on iOS. Enable it if you want to allow to start a new swipe while a cell is already in swiped in a single step. */ -@property (nonatomic) BOOL touchOnDismissSwipe; - -/** Optional background color for swipe overlay. If not set, its inferred automatically from the cell contentView */ -@property (nonatomic, strong, nullable) UIColor * swipeBackgroundColor; -/** Property to read or change the current swipe offset programmatically */ -@property (nonatomic, assign) CGFloat swipeOffset; - -/** Utility methods to show or hide swipe buttons programmatically */ --(void) hideSwipeAnimated: (BOOL) animated; --(void) hideSwipeAnimated: (BOOL) animated completion:(nullable void(^)(BOOL finished)) completion; --(void) showSwipe: (MGSwipeDirection) direction animated: (BOOL) animated; --(void) showSwipe: (MGSwipeDirection) direction animated: (BOOL) animated completion:(nullable void(^)(BOOL finished)) completion; --(void) setSwipeOffset:(CGFloat)offset animated: (BOOL) animated completion:(nullable void(^)(BOOL finished)) completion; --(void) setSwipeOffset:(CGFloat)offset animation: (nullable MGSwipeAnimation *) animation completion:(nullable void(^)(BOOL finished)) completion; --(void) expandSwipe: (MGSwipeDirection) direction animated: (BOOL) animated; - -/** Refresh method to be used when you want to update the cell contents while the user is swiping */ --(void) refreshContentView; -/** Refresh method to be used when you want to dynamically change the left or right buttons (add or remove) - * If you only want to change the title or the backgroundColor of a button you can change it's properties (get the button instance from leftButtons or rightButtons arrays) - * @param usingDelegate if YES new buttons will be fetched using the MGSwipeTableCellDelegate. Otherwise new buttons will be fetched from leftButtons/rightButtons properties. - */ --(void) refreshButtons: (BOOL) usingDelegate; - -@end - diff --git a/Libraries external/MGSwipeTableCell/MGSwipeTableCell.m b/Libraries external/MGSwipeTableCell/MGSwipeTableCell.m deleted file mode 100755 index 267f14b2b..000000000 --- a/Libraries external/MGSwipeTableCell/MGSwipeTableCell.m +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * MGSwipeTableCell is licensed under MIT license. See LICENSE.md file for more information. - * Copyright (c) 2016 Imanol Fernandez @MortimerGoro - */ - -#import "MGSwipeTableCell.h" - -#pragma mark Input Overlay Helper Class -/** Used to capture table input while swipe buttons are visible*/ -@interface MGSwipeTableInputOverlay : UIView -@property (nonatomic, weak) MGSwipeTableCell * currentCell; -@end - -@implementation MGSwipeTableInputOverlay - --(id) initWithFrame:(CGRect)frame -{ - if (self = [super initWithFrame:frame]) { - self.backgroundColor = [UIColor clearColor]; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - } - return self; -} - --(UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event -{ - if (event == nil) { - return nil; - } - if (!_currentCell) { - [self removeFromSuperview]; - return nil; - } - CGPoint p = [self convertPoint:point toView:_currentCell]; - if (_currentCell && (_currentCell.hidden || CGRectContainsPoint(_currentCell.bounds, p))) { - return nil; - } - BOOL hide = YES; - if (_currentCell && _currentCell.delegate && [_currentCell.delegate respondsToSelector:@selector(swipeTableCell:shouldHideSwipeOnTap:)]) { - hide = [_currentCell.delegate swipeTableCell:_currentCell shouldHideSwipeOnTap:p]; - } - if (hide) { - [_currentCell hideSwipeAnimated:YES]; - } - return _currentCell.touchOnDismissSwipe ? nil : self; -} - -@end - -#pragma mark Button Container View and transitions - -@interface MGSwipeButtonsView : UIView -@property (nonatomic, weak) MGSwipeTableCell * cell; -@property (nonatomic, strong) UIColor * backgroundColorCopy; -@end - -@implementation MGSwipeButtonsView -{ - NSArray * _buttons; - UIView * _container; - BOOL _fromLeft; - UIView * _expandedButton; - UIView * _expandedButtonAnimated; - UIView * _expansionBackground; - UIView * _expansionBackgroundAnimated; - CGRect _expandedButtonBoundsCopy; - MGSwipeExpansionLayout _expansionLayout; - CGFloat _expansionOffset; - CGFloat _buttonsDistance; - BOOL _autoHideExpansion; -} - -#pragma mark Layout - --(instancetype) initWithButtons:(NSArray*) buttonsArray direction:(MGSwipeDirection) direction differentWidth:(BOOL) differentWidth buttonsDistance:(CGFloat) buttonsDistance -{ - CGFloat containerWidth = 0; - CGSize maxSize = CGSizeZero; - UIView* lastButton = [buttonsArray lastObject]; - for (UIView * button in buttonsArray) { - containerWidth += button.bounds.size.width + (lastButton == button ? 0 : buttonsDistance); - maxSize.width = MAX(maxSize.width, button.bounds.size.width); - maxSize.height = MAX(maxSize.height, button.bounds.size.height); - } - if (!differentWidth) { - containerWidth = maxSize.width * buttonsArray.count + buttonsDistance * (buttonsArray.count - 1); - } - - if (self = [super initWithFrame:CGRectMake(0, 0, containerWidth, maxSize.height)]) { - _fromLeft = direction == MGSwipeDirectionLeftToRight; - _buttonsDistance = buttonsDistance; - _container = [[UIView alloc] initWithFrame:self.bounds]; - _container.clipsToBounds = YES; - _container.backgroundColor = [UIColor clearColor]; - [self addSubview:_container]; - _buttons = _fromLeft ? buttonsArray: [[buttonsArray reverseObjectEnumerator] allObjects]; - for (UIView * button in _buttons) { - if ([button isKindOfClass:[UIButton class]]) { - UIButton * btn = (UIButton*)button; - [btn removeTarget:nil action:@selector(mgButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; //Remove all targets to avoid problems with reused buttons among many cells - [btn addTarget:self action:@selector(mgButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; - } - if (!differentWidth) { - button.frame = CGRectMake(0, 0, maxSize.width, maxSize.height); - } - button.autoresizingMask = UIViewAutoresizingFlexibleHeight; - [_container insertSubview:button atIndex: _fromLeft ? 0: _container.subviews.count]; - } - [self resetButtons]; - } - return self; -} - --(void) dealloc -{ - for (UIView * button in _buttons) { - if ([button isKindOfClass:[UIButton class]]) { - [(UIButton *)button removeTarget:self action:@selector(mgButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; - } - } -} - --(void) resetButtons -{ - CGFloat offsetX = 0; - UIView* lastButton = [_buttons lastObject]; - for (UIView * button in _buttons) { - button.frame = CGRectMake(offsetX, 0, button.bounds.size.width, self.bounds.size.height); - button.autoresizingMask = UIViewAutoresizingFlexibleHeight; - offsetX += button.bounds.size.width + (lastButton == button ? 0 : _buttonsDistance); - } -} - --(void) layoutExpansion: (CGFloat) offset -{ - _expansionOffset = offset; - _container.frame = CGRectMake(_fromLeft ? 0: self.bounds.size.width - offset, 0, offset, self.bounds.size.height); - if (_expansionBackgroundAnimated && _expandedButtonAnimated) { - _expansionBackgroundAnimated.frame = [self expansionBackgroundRect:_expandedButtonAnimated]; - } -} - --(void) layoutSubviews -{ - [super layoutSubviews]; - if (_expandedButton) { - [self layoutExpansion:_expansionOffset]; - } - else { - _container.frame = self.bounds; - } -} - --(CGRect) expansionBackgroundRect: (UIView *) button -{ - CGFloat extra = 100.0f; //extra size to avoid expansion background size issue on iOS 7.0 - if (_fromLeft) { - return CGRectMake(-extra, 0, button.frame.origin.x + extra, _container.bounds.size.height); - } - else { - return CGRectMake(button.frame.origin.x + button.bounds.size.width, 0, - _container.bounds.size.width - (button.frame.origin.x + button.bounds.size.width ) + extra - ,_container.bounds.size.height); - } - -} - --(void) expandToOffset:(CGFloat) offset settings:(MGSwipeExpansionSettings*) settings -{ - if (settings.buttonIndex < 0 || settings.buttonIndex >= _buttons.count) { - return; - } - if (!_expandedButton) { - _expandedButton = [_buttons objectAtIndex: _fromLeft ? settings.buttonIndex : _buttons.count - settings.buttonIndex - 1]; - CGRect previusRect = _container.frame; - [self layoutExpansion:offset]; - [self resetButtons]; - if (!_fromLeft) { //Fix expansion animation for right buttons - for (UIView * button in _buttons) { - CGRect frame = button.frame; - frame.origin.x += _container.bounds.size.width - previusRect.size.width; - button.frame = frame; - } - } - _expansionBackground = [[UIView alloc] initWithFrame:[self expansionBackgroundRect:_expandedButton]]; - _expansionBackground.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - if (settings.expansionColor) { - _backgroundColorCopy = _expandedButton.backgroundColor; - _expandedButton.backgroundColor = settings.expansionColor; - } - _expansionBackground.backgroundColor = _expandedButton.backgroundColor; - if (UIColor.clearColor == _expandedButton.backgroundColor) { - // Provides access to more complex content for display on the background - _expansionBackground.layer.contents = _expandedButton.layer.contents; - } - [_container addSubview:_expansionBackground]; - _expansionLayout = settings.expansionLayout; - - CGFloat duration = _fromLeft ? _cell.leftExpansion.animationDuration : _cell.rightExpansion.animationDuration; - [UIView animateWithDuration: duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ - _expandedButton.hidden = NO; - - if (_expansionLayout == MGSwipeExpansionLayoutCenter) { - _expandedButtonBoundsCopy = _expandedButton.bounds; - _expandedButton.layer.mask = nil; - _expandedButton.layer.transform = CATransform3DIdentity; - _expandedButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - [_expandedButton.superview bringSubviewToFront:_expandedButton]; - _expandedButton.frame = _container.bounds; - _expansionBackground.frame = [self expansionBackgroundRect:_expandedButton]; - } - else if (_expansionLayout == MGSwipeExpansionLayoutNone) { - [_expandedButton.superview bringSubviewToFront:_expandedButton]; - _expansionBackground.frame = _container.bounds; - } - else if (_fromLeft) { - _expandedButton.frame = CGRectMake(_container.bounds.size.width - _expandedButton.bounds.size.width, 0, _expandedButton.bounds.size.width, _expandedButton.bounds.size.height); - _expandedButton.autoresizingMask|= UIViewAutoresizingFlexibleLeftMargin; - _expansionBackground.frame = [self expansionBackgroundRect:_expandedButton]; - } - else { - _expandedButton.frame = CGRectMake(0, 0, _expandedButton.bounds.size.width, _expandedButton.bounds.size.height); - _expandedButton.autoresizingMask|= UIViewAutoresizingFlexibleRightMargin; - _expansionBackground.frame = [self expansionBackgroundRect:_expandedButton]; - } - - } completion:^(BOOL finished) { - }]; - return; - } - [self layoutExpansion:offset]; -} - --(void) endExpansionAnimated:(BOOL) animated -{ - if (_expandedButton) { - _expandedButtonAnimated = _expandedButton; - if (_expansionBackgroundAnimated && _expansionBackgroundAnimated != _expansionBackground) { - [_expansionBackgroundAnimated removeFromSuperview]; - } - _expansionBackgroundAnimated = _expansionBackground; - _expansionBackground = nil; - _expandedButton = nil; - if (_backgroundColorCopy) { - _expansionBackgroundAnimated.backgroundColor = _backgroundColorCopy; - _expandedButtonAnimated.backgroundColor = _backgroundColorCopy; - _backgroundColorCopy = nil; - } - CGFloat duration = _fromLeft ? _cell.leftExpansion.animationDuration : _cell.rightExpansion.animationDuration; - [UIView animateWithDuration: animated ? duration : 0.0 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ - _container.frame = self.bounds; - if (_expansionLayout == MGSwipeExpansionLayoutCenter) { - _expandedButtonAnimated.frame = _expandedButtonBoundsCopy; - } - [self resetButtons]; - _expansionBackgroundAnimated.frame = [self expansionBackgroundRect:_expandedButtonAnimated]; - } completion:^(BOOL finished) { - [_expansionBackgroundAnimated removeFromSuperview]; - }]; - } - else if (_expansionBackground) { - [_expansionBackground removeFromSuperview]; - _expansionBackground = nil; - } -} - --(UIView*) getExpandedButton -{ - return _expandedButton; -} - -#pragma mark Trigger Actions - --(BOOL) handleClick: (id) sender fromExpansion:(BOOL) fromExpansion -{ - bool autoHide = false; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wundeclared-selector" - if ([sender respondsToSelector:@selector(callMGSwipeConvenienceCallback:)]) { - //call convenience block callback if exits (usage of MGSwipeButton class is not compulsory) - autoHide = [sender performSelector:@selector(callMGSwipeConvenienceCallback:) withObject:_cell]; - } -#pragma clang diagnostic pop - - if (_cell.delegate && [_cell.delegate respondsToSelector:@selector(swipeTableCell:tappedButtonAtIndex:direction:fromExpansion:)]) { - NSInteger index = [_buttons indexOfObject:sender]; - if (!_fromLeft) { - index = _buttons.count - index - 1; //right buttons are reversed - } - autoHide|= [_cell.delegate swipeTableCell:_cell tappedButtonAtIndex:index direction:_fromLeft ? MGSwipeDirectionLeftToRight : MGSwipeDirectionRightToLeft fromExpansion:fromExpansion]; - } - - if (fromExpansion && autoHide) { - _expandedButton = nil; - _cell.swipeOffset = 0; - } - else if (autoHide) { - [_cell hideSwipeAnimated:YES]; - } - - return autoHide; - -} -//button listener --(void) mgButtonClicked: (id) sender -{ - [self handleClick:sender fromExpansion:NO]; -} - - -#pragma mark Transitions - --(void) transitionStatic:(CGFloat) t -{ - const CGFloat dx = self.bounds.size.width * (1.0 - t); - CGFloat offsetX = 0; - - UIView* lastButton = [_buttons lastObject]; - for (UIView *button in _buttons) { - CGRect frame = button.frame; - frame.origin.x = offsetX + (_fromLeft ? dx : -dx); - button.frame = frame; - offsetX += frame.size.width + (button == lastButton ? 0 : _buttonsDistance); - } -} - --(void) transitionDrag:(CGFloat) t -{ - //No Op, nothing to do ;) -} - --(void) transitionClip:(CGFloat) t -{ - CGFloat selfWidth = self.bounds.size.width; - CGFloat offsetX = 0; - - UIView* lastButton = [_buttons lastObject]; - for (UIView *button in _buttons) { - CGRect frame = button.frame; - CGFloat dx = roundf(frame.size.width * 0.5 * (1.0 - t)) ; - frame.origin.x = _fromLeft ? (selfWidth - frame.size.width - offsetX) * (1.0 - t) + offsetX + dx : offsetX * t - dx; - button.frame = frame; - - if (_buttons.count > 1) { - CAShapeLayer *maskLayer = [CAShapeLayer new]; - CGRect maskRect = CGRectMake(dx - 0.5, 0, frame.size.width - 2 * dx + 1.5, frame.size.height); - CGPathRef path = CGPathCreateWithRect(maskRect, NULL); - maskLayer.path = path; - CGPathRelease(path); - button.layer.mask = maskLayer; - } - - offsetX += frame.size.width + (button == lastButton ? 0 : _buttonsDistance); - } -} - --(void) transtitionFloatBorder:(CGFloat) t -{ - CGFloat selfWidth = self.bounds.size.width; - CGFloat offsetX = 0; - - UIView* lastButton = [_buttons lastObject]; - for (UIView *button in _buttons) { - CGRect frame = button.frame; - frame.origin.x = _fromLeft ? (selfWidth - frame.size.width - offsetX) * (1.0 - t) + offsetX : offsetX * t; - button.frame = frame; - offsetX += frame.size.width + (button == lastButton ? 0 : _buttonsDistance); - } -} - --(void) transition3D:(CGFloat) t -{ - const CGFloat invert = _fromLeft ? 1.0 : -1.0; - const CGFloat angle = M_PI_2 * (1.0 - t) * invert; - CATransform3D transform = CATransform3DIdentity; - transform.m34 = -1.0/400.0f; //perspective 1/z - const CGFloat dx = -_container.bounds.size.width * 0.5 * invert; - const CGFloat offset = dx * 2 * (1.0 - t); - transform = CATransform3DTranslate(transform, dx - offset, 0, 0); - transform = CATransform3DRotate(transform, angle, 0.0, 1.0, 0.0); - transform = CATransform3DTranslate(transform, -dx, 0, 0); - _container.layer.transform = transform; -} - --(void) transition:(MGSwipeTransition) mode percent:(CGFloat) t -{ - switch (mode) { - case MGSwipeTransitionStatic: [self transitionStatic:t]; break; - case MGSwipeTransitionDrag: [self transitionDrag:t]; break; - case MGSwipeTransitionClipCenter: [self transitionClip:t]; break; - case MGSwipeTransitionBorder: [self transtitionFloatBorder:t]; break; - case MGSwipeTransitionRotate3D: [self transition3D:t]; break; - } - if (_expandedButtonAnimated && _expansionBackgroundAnimated) { - _expansionBackgroundAnimated.frame = [self expansionBackgroundRect:_expandedButtonAnimated]; - } -} - -@end - -#pragma mark Settings Classes -@implementation MGSwipeSettings --(instancetype) init -{ - if (self = [super init]) { - self.transition = MGSwipeTransitionBorder; - self.threshold = 0.5; - self.offset = 0; - self.keepButtonsSwiped = YES; - self.enableSwipeBounces = YES; - self.swipeBounceRate = 1.0; - self.showAnimation = [[MGSwipeAnimation alloc] init]; - self.hideAnimation = [[MGSwipeAnimation alloc] init]; - self.stretchAnimation = [[MGSwipeAnimation alloc] init]; - } - return self; -} - --(void) setAnimationDuration:(CGFloat)duration -{ - _showAnimation.duration = duration; - _hideAnimation.duration = duration; - _stretchAnimation.duration = duration; -} - --(CGFloat) animationDuration { - return _showAnimation.duration; -} - -@end - -@implementation MGSwipeExpansionSettings --(instancetype) init -{ - if (self = [super init]) { - self.buttonIndex = -1; - self.threshold = 1.3; - self.animationDuration = 0.2; - self.triggerAnimation = [[MGSwipeAnimation alloc] init]; - } - return self; -} -@end - -@interface MGSwipeAnimationData : NSObject -@property (nonatomic, assign) CGFloat from; -@property (nonatomic, assign) CGFloat to; -@property (nonatomic, assign) CFTimeInterval duration; -@property (nonatomic, assign) CFTimeInterval start; -@property (nonatomic, strong) MGSwipeAnimation * animation; - -@end - -@implementation MGSwipeAnimationData -@end - - -#pragma mark Easing Functions and MGSwipeAnimation - -static inline CGFloat mgEaseLinear(CGFloat t, CGFloat b, CGFloat c) { - return c*t + b; -} - -static inline CGFloat mgEaseInQuad(CGFloat t, CGFloat b, CGFloat c) { - return c*t*t + b; -} -static inline CGFloat mgEaseOutQuad(CGFloat t, CGFloat b, CGFloat c) { - return -c*t*(t-2) + b; -} -static inline CGFloat mgEaseInOutQuad(CGFloat t, CGFloat b, CGFloat c) { - if ((t*=2) < 1) return c/2*t*t + b; - --t; - return -c/2 * (t*(t-2) - 1) + b; -} -static inline CGFloat mgEaseInCubic(CGFloat t, CGFloat b, CGFloat c) { - return c*t*t*t + b; -} -static inline CGFloat mgEaseOutCubic(CGFloat t, CGFloat b, CGFloat c) { - --t; - return c*(t*t*t + 1) + b; -} -static inline CGFloat mgEaseInOutCubic(CGFloat t, CGFloat b, CGFloat c) { - if ((t*=2) < 1) return c/2*t*t*t + b; - t-=2; - return c/2*(t*t*t + 2) + b; -} -static inline CGFloat mgEaseOutBounce(CGFloat t, CGFloat b, CGFloat c) { - if (t < (1/2.75)) { - return c*(7.5625*t*t) + b; - } else if (t < (2/2.75)) { - t-=(1.5/2.75); - return c*(7.5625*t*t + .75) + b; - } else if (t < (2.5/2.75)) { - t-=(2.25/2.75); - return c*(7.5625*t*t + .9375) + b; - } else { - t-=(2.625/2.75); - return c*(7.5625*t*t + .984375) + b; - } -}; -static inline CGFloat mgEaseInBounce(CGFloat t, CGFloat b, CGFloat c) { - return c - mgEaseOutBounce (1.0 -t, 0, c) + b; -}; - -static inline CGFloat mgEaseInOutBounce(CGFloat t, CGFloat b, CGFloat c) { - if (t < 0.5) return mgEaseInBounce (t*2, 0, c) * .5 + b; - return mgEaseOutBounce (1.0 - t*2, 0, c) * .5 + c*.5 + b; -}; - -@implementation MGSwipeAnimation - --(instancetype) init { - if (self = [super init]) { - _duration = 0.3; - _easingFunction = MGSwipeEasingFunctionCubicOut; - } - return self; -} - --(CGFloat) value:(CGFloat)elapsed duration:(CGFloat)duration from:(CGFloat)from to:(CGFloat)to -{ - CGFloat t = MIN(elapsed/duration, 1.0f); - if (t == 1.0) { - return to; //precise last value - } - CGFloat (*easingFunction)(CGFloat t, CGFloat b, CGFloat c) = 0; - switch (_easingFunction) { - case MGSwipeEasingFunctionLinear: easingFunction = mgEaseLinear;break; - case MGSwipeEasingFunctionQuadIn: easingFunction = mgEaseInQuad;break; - case MGSwipeEasingFunctionQuadOut: easingFunction = mgEaseOutQuad;break; - case MGSwipeEasingFunctionQuadInOut: easingFunction = mgEaseInOutQuad;break; - case MGSwipeEasingFunctionCubicIn: easingFunction = mgEaseInCubic;break; - default: - case MGSwipeEasingFunctionCubicOut: easingFunction = mgEaseOutCubic;break; - case MGSwipeEasingFunctionCubicInOut: easingFunction = mgEaseInOutCubic;break; - case MGSwipeEasingFunctionBounceIn: easingFunction = mgEaseInBounce;break; - case MGSwipeEasingFunctionBounceOut: easingFunction = mgEaseOutBounce;break; - case MGSwipeEasingFunctionBounceInOut: easingFunction = mgEaseInOutBounce;break; - } - return (*easingFunction)(t, from, to - from); -} - -@end - -#pragma mark MGSwipeTableCell Implementation - - -@implementation MGSwipeTableCell -{ - UITapGestureRecognizer * _tapRecognizer; - UIPanGestureRecognizer * _panRecognizer; - CGPoint _panStartPoint; - CGFloat _panStartOffset; - CGFloat _targetOffset; - - UIView * _swipeOverlay; - UIImageView * _swipeView; - UIView * _swipeContentView; - MGSwipeButtonsView * _leftView; - MGSwipeButtonsView * _rightView; - bool _allowSwipeRightToLeft; - bool _allowSwipeLeftToRight; - __weak MGSwipeButtonsView * _activeExpansion; - - MGSwipeTableInputOverlay * _tableInputOverlay; - bool _overlayEnabled; - __weak UITableView * _cachedParentTable; - UITableViewCellSelectionStyle _previusSelectionStyle; - NSMutableSet * _previusHiddenViews; - BOOL _triggerStateChanges; - - MGSwipeAnimationData * _animationData; - void (^_animationCompletion)(BOOL finished); - CADisplayLink * _displayLink; - MGSwipeState _firstSwipeState; -} - -#pragma mark View creation & layout - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier -{ - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - [self initViews:YES]; - } - return self; -} - -- (id)initWithCoder:(NSCoder*)aDecoder -{ - if(self = [super initWithCoder:aDecoder]) { - [self initViews:YES]; - } - return self; -} - --(void) awakeFromNib -{ - [super awakeFromNib]; - if (!_panRecognizer) { - [self initViews:YES]; - } -} - --(void) dealloc -{ - [self hideSwipeOverlayIfNeeded]; -} - --(void) initViews: (BOOL) cleanButtons -{ - if (cleanButtons) { - _leftButtons = [NSArray array]; - _rightButtons = [NSArray array]; - _leftSwipeSettings = [[MGSwipeSettings alloc] init]; - _rightSwipeSettings = [[MGSwipeSettings alloc] init]; - _leftExpansion = [[MGSwipeExpansionSettings alloc] init]; - _rightExpansion = [[MGSwipeExpansionSettings alloc] init]; - } - _animationData = [[MGSwipeAnimationData alloc] init]; - _panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandler:)]; - [self addGestureRecognizer:_panRecognizer]; - _panRecognizer.delegate = self; - _activeExpansion = nil; - _previusHiddenViews = [NSMutableSet set]; - _swipeState = MGSwipeStateNone; - _triggerStateChanges = YES; - _allowsSwipeWhenTappingButtons = YES; - _preservesSelectionStatus = NO; - _allowsOppositeSwipe = YES; - _firstSwipeState = MGSwipeStateNone; - -} - --(void) cleanViews -{ - [self hideSwipeAnimated:NO]; - if (_displayLink) { - [_displayLink invalidate]; - _displayLink = nil; - } - if (_swipeOverlay) { - [_swipeOverlay removeFromSuperview]; - _swipeOverlay = nil; - } - _leftView = _rightView = nil; - if (_panRecognizer) { - _panRecognizer.delegate = nil; - [self removeGestureRecognizer:_panRecognizer]; - _panRecognizer = nil; - } -} - --(BOOL) isRTLLocale -{ - if ([[UIView class] respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:)]) { - return [UIView userInterfaceLayoutDirectionForSemanticContentAttribute:self.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft; - } -#ifndef TARGET_IS_EXTENSION - else { - return [UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft; - } -#else - return NO; -#endif -} - --(void) fixRegionAndAccesoryViews -{ - //Fix right to left layout direction for arabic and hebrew languagues - if (self.bounds.size.width != self.contentView.bounds.size.width && [self isRTLLocale]) { - _swipeOverlay.frame = CGRectMake(-self.bounds.size.width + self.contentView.bounds.size.width, 0, _swipeOverlay.bounds.size.width, _swipeOverlay.bounds.size.height); - } -} - --(UIView *) swipeContentView -{ - if (!_swipeContentView) { - _swipeContentView = [[UIView alloc] initWithFrame:self.contentView.bounds]; - _swipeContentView.backgroundColor = [UIColor clearColor]; - _swipeContentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _swipeContentView.layer.zPosition = 9; - [self.contentView addSubview:_swipeContentView]; - } - return _swipeContentView; -} - --(void) layoutSubviews -{ - [super layoutSubviews]; - if (_swipeContentView) { - _swipeContentView.frame = self.contentView.bounds; - } - if (_swipeOverlay) { - CGSize prevSize = _swipeView.bounds.size; - _swipeOverlay.frame = CGRectMake(0, 0, self.bounds.size.width, self.contentView.bounds.size.height); - [self fixRegionAndAccesoryViews]; - if (_swipeView.image && !CGSizeEqualToSize(prevSize, _swipeOverlay.bounds.size)) { - //refresh contentView in situations like layout change, orientation chage, table resize, etc. - [self refreshContentView]; - } - } -} - --(void) fetchButtonsIfNeeded -{ - if (_leftButtons.count == 0 && _delegate && [_delegate respondsToSelector:@selector(swipeTableCell:swipeButtonsForDirection:swipeSettings:expansionSettings:)]) { - _leftButtons = [_delegate swipeTableCell:self swipeButtonsForDirection:MGSwipeDirectionLeftToRight swipeSettings:_leftSwipeSettings expansionSettings:_leftExpansion]; - } - if (_rightButtons.count == 0 && _delegate && [_delegate respondsToSelector:@selector(swipeTableCell:swipeButtonsForDirection:swipeSettings:expansionSettings:)]) { - _rightButtons = [_delegate swipeTableCell:self swipeButtonsForDirection:MGSwipeDirectionRightToLeft swipeSettings:_rightSwipeSettings expansionSettings:_rightExpansion]; - } -} - --(void) createSwipeViewIfNeeded -{ - if (!_swipeOverlay) { - _swipeOverlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.contentView.bounds.size.height)]; - [self fixRegionAndAccesoryViews]; - _swipeOverlay.hidden = YES; - _swipeOverlay.backgroundColor = [self backgroundColorForSwipe]; - _swipeOverlay.layer.zPosition = 10; //force render on top of the contentView; - _swipeView = [[UIImageView alloc] initWithFrame:_swipeOverlay.bounds]; - _swipeView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _swipeView.contentMode = UIViewContentModeCenter; - _swipeView.clipsToBounds = YES; - [_swipeOverlay addSubview:_swipeView]; - [self.contentView addSubview:_swipeOverlay]; - } - - [self fetchButtonsIfNeeded]; - if (!_leftView && _leftButtons.count > 0) { - _leftView = [[MGSwipeButtonsView alloc] initWithButtons:_leftButtons direction:MGSwipeDirectionLeftToRight differentWidth:_allowsButtonsWithDifferentWidth buttonsDistance:_leftSwipeSettings.buttonsDistance]; - _leftView.cell = self; - _leftView.frame = CGRectMake(-_leftView.bounds.size.width, _leftSwipeSettings.topMargin, _leftView.bounds.size.width, _swipeOverlay.bounds.size.height - _leftSwipeSettings.topMargin - _leftSwipeSettings.bottomMargin); - _leftView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; - [_swipeOverlay addSubview:_leftView]; - } - if (!_rightView && _rightButtons.count > 0) { - _rightView = [[MGSwipeButtonsView alloc] initWithButtons:_rightButtons direction:MGSwipeDirectionRightToLeft differentWidth:_allowsButtonsWithDifferentWidth buttonsDistance:_rightSwipeSettings.buttonsDistance]; - _rightView.cell = self; - _rightView.frame = CGRectMake(_swipeOverlay.bounds.size.width, _rightSwipeSettings.topMargin, _rightView.bounds.size.width, _swipeOverlay.bounds.size.height - _rightSwipeSettings.topMargin - _rightSwipeSettings.bottomMargin); - _rightView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight; - [_swipeOverlay addSubview:_rightView]; - } -} - - -- (void) showSwipeOverlayIfNeeded -{ - if (_overlayEnabled) { - return; - } - _overlayEnabled = YES; - - if (!_preservesSelectionStatus) - self.selected = NO; - if (_swipeContentView) - [_swipeContentView removeFromSuperview]; - if (_delegate && [_delegate respondsToSelector:@selector(swipeTableCellWillBeginSwiping:)]) { - [_delegate swipeTableCellWillBeginSwiping:self]; - } - - // snapshot cell without separator - CGSize cropSize = CGSizeMake(self.bounds.size.width, self.contentView.bounds.size.height); - _swipeView.image = [self imageFromView:self cropSize:cropSize]; - - _swipeOverlay.hidden = NO; - if (_swipeContentView) - [_swipeView addSubview:_swipeContentView]; - - if (!_allowsMultipleSwipe) { - //input overlay on the whole table - UITableView * table = [self parentTable]; - if (_tableInputOverlay) { - [_tableInputOverlay removeFromSuperview]; - } - _tableInputOverlay = [[MGSwipeTableInputOverlay alloc] initWithFrame:table.bounds]; - _tableInputOverlay.currentCell = self; - [table addSubview:_tableInputOverlay]; - } - - _previusSelectionStyle = self.selectionStyle; - self.selectionStyle = UITableViewCellSelectionStyleNone; - [self setAccesoryViewsHidden:YES]; - - _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapHandler:)]; - _tapRecognizer.cancelsTouchesInView = YES; - _tapRecognizer.delegate = self; - [self addGestureRecognizer:_tapRecognizer]; -} - --(void) hideSwipeOverlayIfNeeded -{ - if (!_overlayEnabled) { - return; - } - _overlayEnabled = NO; - _swipeOverlay.hidden = YES; - _swipeView.image = nil; - if (_swipeContentView) { - [_swipeContentView removeFromSuperview]; - [self.contentView addSubview:_swipeContentView]; - } - - if (_tableInputOverlay) { - [_tableInputOverlay removeFromSuperview]; - _tableInputOverlay = nil; - } - - self.selectionStyle = _previusSelectionStyle; - NSArray * selectedRows = self.parentTable.indexPathsForSelectedRows; - if ([selectedRows containsObject:[self.parentTable indexPathForCell:self]]) { - self.selected = NO; //Hack: in some iOS versions setting the selected property to YES own isn't enough to force the cell to redraw the chosen selectionStyle - self.selected = YES; - } - [self setAccesoryViewsHidden:NO]; - - if (_delegate && [_delegate respondsToSelector:@selector(swipeTableCellWillEndSwiping:)]) { - [_delegate swipeTableCellWillEndSwiping:self]; - } - - if (_tapRecognizer) { - [self removeGestureRecognizer:_tapRecognizer]; - _tapRecognizer = nil; - } -} - --(void) refreshContentView -{ - CGFloat currentOffset = _swipeOffset; - BOOL prevValue = _triggerStateChanges; - _triggerStateChanges = NO; - self.swipeOffset = 0; - self.swipeOffset = currentOffset; - _triggerStateChanges = prevValue; -} - --(void) refreshButtons: (BOOL) usingDelegate -{ - if (usingDelegate) { - self.leftButtons = @[]; - self.rightButtons = @[]; - } - if (_leftView) { - [_leftView removeFromSuperview]; - _leftView = nil; - } - if (_rightView) { - [_rightView removeFromSuperview]; - _rightView = nil; - } - [self createSwipeViewIfNeeded]; - [self refreshContentView]; -} - -#pragma mark Handle Table Events - --(void) willMoveToSuperview:(UIView *)newSuperview; -{ - if (newSuperview == nil) { //remove the table overlay when a cell is removed from the table - [self hideSwipeOverlayIfNeeded]; - } -} - --(void) prepareForReuse -{ - [super prepareForReuse]; - [self cleanViews]; - if (_swipeState != MGSwipeStateNone) { - _triggerStateChanges = YES; - [self updateState:MGSwipeStateNone]; - } - BOOL cleanButtons = _delegate && [_delegate respondsToSelector:@selector(swipeTableCell:swipeButtonsForDirection:swipeSettings:expansionSettings:)]; - [self initViews:cleanButtons]; -} - --(void) setEditing:(BOOL)editing animated:(BOOL)animated -{ - [super setEditing:editing animated:animated]; - if (editing) { //disable swipe buttons when the user sets table editing mode - self.swipeOffset = 0; - } -} - --(void) setEditing:(BOOL)editing -{ - [super setEditing:YES]; - if (editing) { //disable swipe buttons when the user sets table editing mode - self.swipeOffset = 0; - } -} - --(UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event -{ - if (!self.hidden && _swipeOverlay && !_swipeOverlay.hidden) { - //override hitTest to give swipe buttons a higher priority (diclosure buttons can steal input) - UIView * targets[] = {_leftView, _rightView}; - for (int i = 0; i< 2; ++i) { - UIView * target = targets[i]; - if (!target) continue; - - CGPoint p = [self convertPoint:point toView:target]; - if (CGRectContainsPoint(target.bounds, p)) { - return [target hitTest:p withEvent:event]; - } - } - } - return [super hitTest:point withEvent:event]; -} - -#pragma mark Some utility methods - -- (UIImage *)imageFromView:(UIView *)view cropSize:(CGSize)cropSize{ - UIGraphicsBeginImageContextWithOptions(cropSize, NO, [[UIScreen mainScreen] scale]); - [view.layer renderInContext:UIGraphicsGetCurrentContext()]; - UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - --(void) setAccesoryViewsHidden: (BOOL) hidden -{ - if (self.accessoryView) { - self.accessoryView.hidden = hidden; - } - for (UIView * view in self.contentView.superview.subviews) { - if (view != self.contentView && ([view isKindOfClass:[UIButton class]] || [NSStringFromClass(view.class) rangeOfString:@"Disclosure"].location != NSNotFound)) { - view.hidden = hidden; - } - } - - for (UIView * view in self.contentView.subviews) { - if (view == _swipeOverlay || view == _swipeContentView) continue; - if (hidden && !view.hidden) { - view.hidden = YES; - [_previusHiddenViews addObject:view]; - } - else if (!hidden && [_previusHiddenViews containsObject:view]) { - view.hidden = NO; - } - } - - if (!hidden) { - [_previusHiddenViews removeAllObjects]; - } -} - --(UIColor *) backgroundColorForSwipe -{ - if (_swipeBackgroundColor) { - return _swipeBackgroundColor; //user defined color - } - else if (self.contentView.backgroundColor && ![self.contentView.backgroundColor isEqual:[UIColor clearColor]]) { - return self.contentView.backgroundColor; - } - else if (self.backgroundColor) { - return self.backgroundColor; - } - return [UIColor clearColor]; -} - --(UITableView *) parentTable -{ - if (_cachedParentTable) { - return _cachedParentTable; - } - - UIView * view = self.superview; - while(view != nil) { - if([view isKindOfClass:[UITableView class]]) { - _cachedParentTable = (UITableView*) view; - } - view = view.superview; - } - return _cachedParentTable; -} - --(void) updateState: (MGSwipeState) newState; -{ - if (!_triggerStateChanges || _swipeState == newState) { - return; - } - _swipeState = newState; - if (_delegate && [_delegate respondsToSelector:@selector(swipeTableCell:didChangeSwipeState:gestureIsActive:)]) { - [_delegate swipeTableCell:self didChangeSwipeState:_swipeState gestureIsActive: self.isSwipeGestureActive] ; - } -} - -#pragma mark Swipe Animation - -- (void)setSwipeOffset:(CGFloat) newOffset; -{ - CGFloat sign = newOffset > 0 ? 1.0 : -1.0; - MGSwipeButtonsView * activeButtons = sign < 0 ? _rightView : _leftView; - MGSwipeSettings * activeSettings = sign < 0 ? _rightSwipeSettings : _leftSwipeSettings; - - if(activeSettings.enableSwipeBounces) { - _swipeOffset = newOffset; - - CGFloat maxUnbouncedOffset = sign * activeButtons.bounds.size.width; - - if ((sign > 0 && newOffset > maxUnbouncedOffset) || (sign < 0 && newOffset < maxUnbouncedOffset)) { - _swipeOffset = maxUnbouncedOffset + (newOffset - maxUnbouncedOffset) * activeSettings.swipeBounceRate; - } - } - else { - CGFloat maxOffset = sign * activeButtons.bounds.size.width; - _swipeOffset = sign > 0 ? MIN(newOffset, maxOffset) : MAX(newOffset, maxOffset); - } - CGFloat offset = fabs(_swipeOffset); - - - if (!activeButtons || offset == 0) { - if (_leftView) - [_leftView endExpansionAnimated:NO]; - if (_rightView) - [_rightView endExpansionAnimated:NO]; - [self hideSwipeOverlayIfNeeded]; - _targetOffset = 0; - [self updateState:MGSwipeStateNone]; - return; - } - else { - [self showSwipeOverlayIfNeeded]; - CGFloat swipeThreshold = activeSettings.threshold; - BOOL keepButtons = activeSettings.keepButtonsSwiped; - _targetOffset = keepButtons && offset > activeButtons.bounds.size.width * swipeThreshold ? activeButtons.bounds.size.width * sign : 0; - } - - BOOL onlyButtons = activeSettings.onlySwipeButtons; - _swipeView.transform = CGAffineTransformMakeTranslation(onlyButtons ? 0 : _swipeOffset, 0); - - //animate existing buttons - MGSwipeButtonsView* but[2] = {_leftView, _rightView}; - MGSwipeSettings* settings[2] = {_leftSwipeSettings, _rightSwipeSettings}; - MGSwipeExpansionSettings * expansions[2] = {_leftExpansion, _rightExpansion}; - - for (int i = 0; i< 2; ++i) { - MGSwipeButtonsView * view = but[i]; - if (!view) continue; - - //buttons view position - CGFloat translation = MIN(offset, view.bounds.size.width) * sign + settings[i].offset * sign; - view.transform = CGAffineTransformMakeTranslation(translation, 0); - - if (view != activeButtons) continue; //only transition if active (perf. improvement) - bool expand = expansions[i].buttonIndex >= 0 && offset > view.bounds.size.width * expansions[i].threshold; - if (expand) { - [view expandToOffset:offset settings:expansions[i]]; - _targetOffset = expansions[i].fillOnTrigger ? self.bounds.size.width * sign : 0; - _activeExpansion = view; - [self updateState:i ? MGSwipeStateExpandingRightToLeft : MGSwipeStateExpandingLeftToRight]; - } - else { - [view endExpansionAnimated:YES]; - _activeExpansion = nil; - CGFloat t = MIN(1.0f, offset/view.bounds.size.width); - [view transition:settings[i].transition percent:t]; - [self updateState:i ? MGSwipeStateSwipingRightToLeft : MGSwipeStateSwipingLeftToRight]; - } - } -} - --(void) hideSwipeAnimated: (BOOL) animated completion:(void(^)(BOOL finished)) completion -{ - MGSwipeAnimation * animation = animated ? (_swipeOffset > 0 ? _leftSwipeSettings.hideAnimation: _rightSwipeSettings.hideAnimation) : nil; - [self setSwipeOffset:0 animation:animation completion:completion]; -} - --(void) hideSwipeAnimated: (BOOL) animated -{ - [self hideSwipeAnimated:animated completion:nil]; -} - --(void) showSwipe: (MGSwipeDirection) direction animated: (BOOL) animated -{ - [self showSwipe:direction animated:animated completion:nil]; -} - --(void) showSwipe: (MGSwipeDirection) direction animated: (BOOL) animated completion:(void(^)(BOOL finished)) completion -{ - [self createSwipeViewIfNeeded]; - _allowSwipeLeftToRight = _leftButtons.count > 0; - _allowSwipeRightToLeft = _rightButtons.count > 0; - UIView * buttonsView = direction == MGSwipeDirectionLeftToRight ? _leftView : _rightView; - - if (buttonsView) { - CGFloat s = direction == MGSwipeDirectionLeftToRight ? 1.0 : -1.0; - MGSwipeAnimation * animation = animated ? (direction == MGSwipeDirectionLeftToRight ? _leftSwipeSettings.showAnimation : _rightSwipeSettings.showAnimation) : nil; - [self setSwipeOffset:buttonsView.bounds.size.width * s animation:animation completion:completion]; - } -} - --(void) expandSwipe: (MGSwipeDirection) direction animated: (BOOL) animated -{ - CGFloat s = direction == MGSwipeDirectionLeftToRight ? 1.0 : -1.0; - MGSwipeExpansionSettings* expSetting = direction == MGSwipeDirectionLeftToRight ? _leftExpansion : _rightExpansion; - - // only perform animation if there's no pending expansion animation and requested direction has fillOnTrigger enabled - if(!_activeExpansion && expSetting.fillOnTrigger) { - [self createSwipeViewIfNeeded]; - _allowSwipeLeftToRight = _leftButtons.count > 0; - _allowSwipeRightToLeft = _rightButtons.count > 0; - UIView * buttonsView = direction == MGSwipeDirectionLeftToRight ? _leftView : _rightView; - - if (buttonsView) { - __weak MGSwipeButtonsView * expansionView = direction == MGSwipeDirectionLeftToRight ? _leftView : _rightView; - __weak MGSwipeTableCell * weakself = self; - [self setSwipeOffset:buttonsView.bounds.size.width * s * expSetting.threshold * 2 animation:expSetting.triggerAnimation completion:^(BOOL finished){ - [expansionView endExpansionAnimated:YES]; - [weakself setSwipeOffset:0 animated:NO completion:nil]; - }]; - } - } -} - --(void) animationTick: (CADisplayLink *) timer -{ - if (!_animationData.start) { - _animationData.start = timer.timestamp; - } - CFTimeInterval elapsed = timer.timestamp - _animationData.start; - bool completed = elapsed >= _animationData.duration; - if (completed) { - _triggerStateChanges = YES; - } - self.swipeOffset = [_animationData.animation value:elapsed duration:_animationData.duration from:_animationData.from to:_animationData.to]; - - //call animation completion and invalidate timer - if (completed){ - [timer invalidate]; - [self invalidateDisplayLink]; - } -} - --(void)invalidateDisplayLink { - [_displayLink invalidate]; - _displayLink = nil; - if (_animationCompletion) { - void (^callbackCopy)(BOOL finished) = _animationCompletion; //copy to avoid duplicated callbacks - _animationCompletion = nil; - callbackCopy(YES); - } -} - --(void) setSwipeOffset:(CGFloat)offset animated: (BOOL) animated completion:(void(^)(BOOL finished)) completion -{ - MGSwipeAnimation * animation = animated ? [[MGSwipeAnimation alloc] init] : nil; - [self setSwipeOffset:offset animation:animation completion:completion]; -} - --(void) setSwipeOffset:(CGFloat)offset animation: (MGSwipeAnimation *) animation completion:(void(^)(BOOL finished)) completion -{ - if (_displayLink) { - [_displayLink invalidate]; - _displayLink = nil; - } - if (_animationCompletion) { //notify previous animation cancelled - void (^callbackCopy)(BOOL finished) = _animationCompletion; //copy to avoid duplicated callbacks - _animationCompletion = nil; - callbackCopy(NO); - } - if (offset !=0) { - [self createSwipeViewIfNeeded]; - } - - if (!animation) { - self.swipeOffset = offset; - if (completion) { - completion(YES); - } - return; - } - - _animationCompletion = completion; - _triggerStateChanges = NO; - _animationData.from = _swipeOffset; - _animationData.to = offset; - _animationData.duration = animation.duration; - _animationData.start = 0; - _animationData.animation = animation; - _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animationTick:)]; - [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; -} - -#pragma mark Gestures - --(void) cancelPanGesture -{ - if (_panRecognizer.state != UIGestureRecognizerStateEnded && _panRecognizer.state != UIGestureRecognizerStatePossible) { - _panRecognizer.enabled = NO; - _panRecognizer.enabled = YES; - if (self.swipeOffset) { - [self hideSwipeAnimated:YES]; - } - } -} - --(void) tapHandler: (UITapGestureRecognizer *) recognizer -{ - BOOL hide = YES; - if (_delegate && [_delegate respondsToSelector:@selector(swipeTableCell:shouldHideSwipeOnTap:)]) { - hide = [_delegate swipeTableCell:self shouldHideSwipeOnTap:[recognizer locationInView:self]]; - } - if (hide) { - [self hideSwipeAnimated:YES]; - } -} - --(CGFloat) filterSwipe: (CGFloat) offset -{ - bool allowed = offset > 0 ? _allowSwipeLeftToRight : _allowSwipeRightToLeft; - UIView * buttons = offset > 0 ? _leftView : _rightView; - if (!buttons || ! allowed) { - offset = 0; - } - else if (!_allowsOppositeSwipe && _firstSwipeState == MGSwipeStateSwipingLeftToRight && offset < 0) { - offset = 0; - } - else if (!_allowsOppositeSwipe && _firstSwipeState == MGSwipeStateSwipingRightToLeft && offset > 0 ) { - offset = 0; - } - return offset; -} - --(void) panHandler: (UIPanGestureRecognizer *)gesture -{ - CGPoint current = [gesture translationInView:self]; - - if (gesture.state == UIGestureRecognizerStateBegan) { - [self invalidateDisplayLink]; - - if (!_preservesSelectionStatus) - self.highlighted = NO; - [self createSwipeViewIfNeeded]; - _panStartPoint = current; - _panStartOffset = _swipeOffset; - if (_swipeOffset != 0) { - _firstSwipeState = _swipeOffset > 0 ? MGSwipeStateSwipingLeftToRight : MGSwipeStateSwipingRightToLeft; - } - - if (!_allowsMultipleSwipe) { - NSArray * cells = [self parentTable].visibleCells; - for (MGSwipeTableCell * cell in cells) { - if ([cell isKindOfClass:[MGSwipeTableCell class]] && cell != self) { - [cell cancelPanGesture]; - } - } - } - } - else if (gesture.state == UIGestureRecognizerStateChanged) { - CGFloat offset = _panStartOffset + current.x - _panStartPoint.x; - if (_firstSwipeState == MGSwipeStateNone) { - _firstSwipeState = offset > 0 ? MGSwipeStateSwipingLeftToRight : MGSwipeStateSwipingRightToLeft; - } - self.swipeOffset = [self filterSwipe:offset]; - } - else { - __weak MGSwipeButtonsView * expansion = _activeExpansion; - if (expansion) { - __weak UIView * expandedButton = [expansion getExpandedButton]; - MGSwipeExpansionSettings * expSettings = _swipeOffset > 0 ? _leftExpansion : _rightExpansion; - UIColor * backgroundColor = nil; - if (!expSettings.fillOnTrigger && expSettings.expansionColor) { - backgroundColor = expansion.backgroundColorCopy; //keep expansion background color - expansion.backgroundColorCopy = expSettings.expansionColor; - } - [self setSwipeOffset:_targetOffset animation:expSettings.triggerAnimation completion:^(BOOL finished){ - if (!finished || self.hidden || !expansion) { - return; //cell might be hidden after a delete row animation without being deallocated (to be reused later) - } - BOOL autoHide = [expansion handleClick:expandedButton fromExpansion:YES]; - if (autoHide) { - [expansion endExpansionAnimated:NO]; - } - if (backgroundColor && expandedButton) { - expandedButton.backgroundColor = backgroundColor; - } - }]; - } - else { - CGFloat velocity = [_panRecognizer velocityInView:self].x; - CGFloat inertiaThreshold = 100.0; //points per second - - if (velocity > inertiaThreshold) { - _targetOffset = _swipeOffset < 0 ? 0 : (_leftView && _leftSwipeSettings.keepButtonsSwiped ? _leftView.bounds.size.width : _targetOffset); - } - else if (velocity < -inertiaThreshold) { - _targetOffset = _swipeOffset > 0 ? 0 : (_rightView && _rightSwipeSettings.keepButtonsSwiped ? -_rightView.bounds.size.width : _targetOffset); - } - _targetOffset = [self filterSwipe:_targetOffset]; - MGSwipeSettings * settings = _swipeOffset > 0 ? _leftSwipeSettings : _rightSwipeSettings; - MGSwipeAnimation * animation = nil; - if (_targetOffset == 0) { - animation = settings.hideAnimation; - } - else if (fabs(_swipeOffset) > fabs(_targetOffset)) { - animation = settings.stretchAnimation; - } - else { - animation = settings.showAnimation; - } - [self setSwipeOffset:_targetOffset animation:animation completion:nil]; - } - - _firstSwipeState = MGSwipeStateNone; - } -} - -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { - - if (gestureRecognizer == _panRecognizer) { - - if (self.isEditing) { - return NO; //do not swipe while editing table - } - - CGPoint translation = [_panRecognizer translationInView:self]; - if (fabs(translation.y) > fabs(translation.x)) { - return NO; // user is scrolling vertically - } - if (_swipeView) { - CGPoint point = [_tapRecognizer locationInView:_swipeView]; - if (!CGRectContainsPoint(_swipeView.bounds, point)) { - return _allowsSwipeWhenTappingButtons; //user clicked outside the cell or in the buttons area - } - } - - if (_swipeOffset != 0.0) { - return YES; //already swiped, don't need to check buttons or canSwipe delegate - } - - //make a decision according to existing buttons or using the optional delegate - if (_delegate && [_delegate respondsToSelector:@selector(swipeTableCell:canSwipe:fromPoint:)]) { - CGPoint point = [_panRecognizer locationInView:self]; - _allowSwipeLeftToRight = [_delegate swipeTableCell:self canSwipe:MGSwipeDirectionLeftToRight fromPoint:point]; - _allowSwipeRightToLeft = [_delegate swipeTableCell:self canSwipe:MGSwipeDirectionRightToLeft fromPoint:point]; - } - else if (_delegate && [_delegate respondsToSelector:@selector(swipeTableCell:canSwipe:)]) { - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - _allowSwipeLeftToRight = [_delegate swipeTableCell:self canSwipe:MGSwipeDirectionLeftToRight]; - _allowSwipeRightToLeft = [_delegate swipeTableCell:self canSwipe:MGSwipeDirectionRightToLeft]; - #pragma clang diagnostic pop - } - else { - [self fetchButtonsIfNeeded]; - _allowSwipeLeftToRight = _leftButtons.count > 0; - _allowSwipeRightToLeft = _rightButtons.count > 0; - } - - return (_allowSwipeLeftToRight && translation.x > 0) || (_allowSwipeRightToLeft && translation.x < 0); - } - else if (gestureRecognizer == _tapRecognizer) { - CGPoint point = [_tapRecognizer locationInView:_swipeView]; - return CGRectContainsPoint(_swipeView.bounds, point); - } - return YES; -} - --(BOOL) isSwipeGestureActive -{ - return _panRecognizer.state == UIGestureRecognizerStateBegan || _panRecognizer.state == UIGestureRecognizerStateChanged; -} - --(void)setSwipeBackgroundColor:(UIColor *)swipeBackgroundColor { - _swipeBackgroundColor = swipeBackgroundColor; - if (_swipeOverlay) { - _swipeOverlay.backgroundColor = swipeBackgroundColor; - } -} - -#pragma mark Accessibility - -- (NSInteger)accessibilityElementCount { - return _swipeOffset == 0 ? [super accessibilityElementCount] : 1; -} - -- (id)accessibilityElementAtIndex:(NSInteger)index { - return _swipeOffset == 0 ? [super accessibilityElementAtIndex:index] : self.contentView; -} - -- (NSInteger)indexOfAccessibilityElement:(id)element { - return _swipeOffset == 0 ? [super indexOfAccessibilityElement:element] : 0; -} - - -@end |