SwipeTableCell.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. //
  2. // SwipeTableCell.m
  3. // SwipeTableView
  4. //
  5. // Created by zhao on 16/8/11.
  6. // Copyright © 2016年 zhaoName. All rights reserved.
  7. //
  8. #import "SwipeTableCell.h"
  9. #define CELL_WIDTH self.bounds.size.width
  10. #define CELL_HEIGHT self.bounds.size.height
  11. @interface SwipeTableCell ()<UIGestureRecognizerDelegate>
  12. @property (nonatomic, strong) UITableView *tableView; /**< 当前cell所在的tableView*/
  13. @property (nonatomic, strong) UIView *swipeOverlayView; /**< 滑动时覆盖在cell上*/
  14. @property (nonatomic, strong) UIImageView *swipeImageView; /**< 显示移动后的cell上的内容*/
  15. @property (nonatomic, strong) SwipeView *rightSwipeView; /**< 右滑展示的view*/
  16. @property (nonatomic, strong) SwipeView *leftSwipeView; /**< 左滑展示的View*/
  17. @property (nonatomic, strong) SwipeView *gestureAnimationSwipeView;
  18. @property (nonatomic, assign) SwipeTableCellStyle swipeStyle; /**< 滑动样式 默认右滑*/
  19. @property (nonatomic, assign) SwipeViewTransfromMode transformMode; /**< swipeView的弹出效果*/
  20. @property (nonatomic, strong) NSArray<SwipeButton *> *leftSwipeButtons; /**< 左滑buttons*/
  21. @property (nonatomic, strong) NSArray<SwipeButton *> *rightSwipeButtons; /**< 右滑buttons*/
  22. @property (nonatomic, strong) NSMutableSet *perviusHiddenViewSet;/**< 已经隐藏的view*/
  23. @property (nonatomic, assign) CGFloat swipeOffset; /**< 滑动偏移量*/
  24. @property (nonatomic, assign) CGFloat targetOffset; /**< 最终目标偏移量*/
  25. @property (nonatomic, strong) UIPanGestureRecognizer *panGesture; /**< 滑动手势*/
  26. @property (nonatomic, strong) UITapGestureRecognizer *tapGesture; /**< 点击手势*/
  27. @property (nonatomic, assign) CGPoint panStartPoint; /**<滑动手势开始点击的坐标*/
  28. @property (nonatomic, assign) CGFloat panStartOffset; /**<滑动手势的偏移量*/
  29. @property (nonatomic, assign) BOOL isShowSwipeOverlayView; /**< 保证显示、隐藏swipeImageView方法只走一次*/
  30. @property (nonatomic, strong) CADisplayLink *dispalyLink; /**<定时器 一秒60次*/
  31. @property (nonatomic, assign) UITableViewCellSelectionStyle previousSelectStyle;/**< 先前cell的选中样式*/
  32. @end
  33. @implementation SwipeTableCell
  34. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  35. {
  36. if([super initWithStyle:style reuseIdentifier:reuseIdentifier])
  37. {
  38. [self initDatas];
  39. }
  40. return self;
  41. }
  42. - (instancetype)initWithCoder:(NSCoder *)aDecoder
  43. {
  44. if([super initWithCoder:aDecoder])
  45. {
  46. [self initDatas];
  47. }
  48. return self;
  49. }
  50. - (void)awakeFromNib
  51. {
  52. [super awakeFromNib];
  53. [self initDatas];
  54. }
  55. /**
  56. * 初始化数据
  57. */
  58. - (void)initDatas
  59. {
  60. self.swipeStyle = SwipeTableCellStyleRightToLeft; //默认右滑
  61. self.transformMode = SwipeViewTransfromModeDefault;
  62. self.swipeOffset = 0.0;
  63. self.targetOffset = 0.0;
  64. self.swipeThreshold = 0.5;
  65. self.isAllowMultipleSwipe = NO;
  66. self.isShowSwipeOverlayView = NO;
  67. _hideSwipeViewWhenScrollTableView = YES;
  68. self.hideSwipeViewWhenClickSwipeButton = YES;
  69. self.swipeOverlayViewBackgroundColor = [UIColor clearColor];
  70. self.selectionStyle = UITableViewCellSelectionStyleNone;
  71. self.isAllowExpand = YES;
  72. self.expandThreshold = 1.5;
  73. // self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureRecognizer:)];
  74. // self.panGesture.delegate = self;
  75. // [self addGestureRecognizer:self.panGesture];
  76. }
  77. /**
  78. * 复用问题
  79. */
  80. - (void)prepareForReuse
  81. {
  82. [super prepareForReuse];
  83. if(self.panGesture)
  84. {
  85. self.panGesture.delegate = nil;
  86. [self removeGestureRecognizer:self.panGesture];
  87. self.panGesture = nil;
  88. }
  89. if(self.swipeOverlayView)
  90. {
  91. [self.swipeOverlayView removeFromSuperview];
  92. self.swipeOverlayView = nil;
  93. _rightSwipeView = _leftSwipeView = nil;
  94. self.rightSwipeButtons = @[];
  95. self.leftSwipeButtons = @[];
  96. }
  97. if(self.dispalyLink)
  98. {
  99. [self.dispalyLink invalidate];
  100. self.dispalyLink = nil;
  101. }
  102. [self initDatas];
  103. }
  104. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
  105. {
  106. UIView *view = [super hitTest:point withEvent:event];
  107. if (!view)
  108. {
  109. // bug fixed: swipeView显示后再次拖动swipeView 会出现快速闪动现象
  110. NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
  111. if (indexPath != nil || point.y < 0) return view;
  112. // 若点击区域在tableView上 而不在cell上,滑动时也会自动隐藏swipeView
  113. for(SwipeTableCell *cell in self.tableView.visibleCells) // 滑动cell时,自动隐藏swipeView
  114. {
  115. if(cell.hideSwipeViewWhenScrollTableView && !cell.swipeOverlayView.hidden)
  116. {
  117. [cell hiddenSwipeAnimationAtCell:YES];
  118. }
  119. }
  120. }
  121. return view;
  122. }
  123. // 更改滑动按钮的内容 如置顶变成取消置顶
  124. - (void)refreshButtonContent
  125. {
  126. if(self.rightSwipeView)
  127. {
  128. [self.rightSwipeView removeFromSuperview];
  129. self.rightSwipeView = nil;
  130. }
  131. if(self.leftSwipeView)
  132. {
  133. [self.leftSwipeView removeFromSuperview];
  134. self.leftSwipeView = nil;
  135. }
  136. self.rightSwipeButtons = @[];
  137. self.leftSwipeButtons = @[];
  138. [self getSwipeButtons];
  139. [self createSwipeOverlayViewIfNeed];
  140. }
  141. #pragma mark -- 处理滑动手势
  142. /**
  143. * 处理滑动手势 上左x<0、y<0 下右x>0、y>0
  144. */
  145. - (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)pan
  146. {
  147. CGPoint currentPanPoint = [pan translationInView:self];
  148. if(pan.state == UIGestureRecognizerStateBegan)
  149. {
  150. self.panStartPoint = currentPanPoint;
  151. self.panStartOffset = self.swipeOffset;
  152. [self createSwipeOverlayViewIfNeed];
  153. // 不允许多个cell同时能滑动,则移除上一个cell的滑动手势
  154. if(!_isAllowMultipleSwipe)
  155. {
  156. for(SwipeTableCell * cell in self.tableView.visibleCells)
  157. {
  158. if(cell != self) [cell cancelPanGesture];
  159. }
  160. }
  161. }
  162. else if(pan.state == UIGestureRecognizerStateChanged)
  163. {
  164. CGFloat offset = self.panStartOffset + currentPanPoint.x - self.panStartPoint.x;
  165. // 重新swipeOffset的setter方法,监测滑动偏移量
  166. self.swipeOffset = [self filterSwipeOffset:offset];
  167. }
  168. else if(pan.state == UIGestureRecognizerStateEnded)
  169. {
  170. CGFloat velocity = [self.panGesture velocityInView:self].x;
  171. CGFloat inertiaThreshold = 300; // 每秒走过多少像素
  172. if(velocity > inertiaThreshold) // 快速左滑
  173. {
  174. self.targetOffset = self.swipeOffset < 0 ? 0 : (self.leftSwipeView ? self.leftSwipeView.frame.size.width : self.targetOffset);
  175. }
  176. else if(velocity < -inertiaThreshold) // 快速右滑
  177. {
  178. self.targetOffset = self.swipeOffset > 0 ? 0 : (self.rightSwipeView ? -self.rightSwipeView.frame.size.width : self.targetOffset);
  179. }
  180. self.targetOffset = [self filterSwipeOffset:self.targetOffset];
  181. //NSLog(@"targetOffset:%f", self.targetOffset);
  182. [self gestureAnimationWithOffset:self.targetOffset animationView:self.targetOffset <= 0 ? self.rightSwipeView : self.leftSwipeView];
  183. }
  184. }
  185. /**
  186. * 创建用于显示滑动过后cell内容的SwipeImageView, 并在其上添加滑动按钮
  187. */
  188. - (void)createSwipeOverlayViewIfNeed
  189. {
  190. [self getSwipeTableViewCellStyle];
  191. [self getSwipeButtons];
  192. if(!self.swipeOverlayView)
  193. {
  194. _swipeOverlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CELL_WIDTH, CELL_HEIGHT)];
  195. _swipeOverlayView.backgroundColor = self.swipeOverlayViewBackgroundColor;
  196. _swipeOverlayView.hidden = YES;
  197. _swipeImageView = [[UIImageView alloc] initWithFrame:self.swipeOverlayView.bounds];
  198. _swipeImageView.userInteractionEnabled = YES;
  199. [_swipeOverlayView addSubview:_swipeImageView];
  200. [self.contentView addSubview:self.swipeOverlayView];
  201. }
  202. // 获取swipeButton距swipeTableView上左下右的距离
  203. UIEdgeInsets edge = UIEdgeInsetsZero;
  204. if ([self.swipeDelegate respondsToSelector:@selector(tableView:swipeButtonEdgeAtIndexPath:)]) {
  205. edge = [self.swipeDelegate tableView:self.tableView swipeButtonEdgeAtIndexPath:[self.tableView indexPathForCell:self]];
  206. }
  207. if(self.rightSwipeButtons.count && !self.rightSwipeView)
  208. {
  209. _rightSwipeView = [[SwipeView alloc] initWithButtons:self.rightSwipeButtons fromRight:YES cellHeght:CELL_HEIGHT edge:edge];
  210. // 改变rightSwipeView的frame 使其显示在swipeImageView的最右端
  211. _rightSwipeView.frame = CGRectMake(self.swipeImageView.bounds.size.width, 0, _rightSwipeView.frame.size.width, CELL_HEIGHT);
  212. [self.swipeOverlayView addSubview:_rightSwipeView];
  213. }
  214. if(self.leftSwipeButtons.count && !self.leftSwipeView)
  215. {
  216. _leftSwipeView = [[SwipeView alloc] initWithButtons:self.leftSwipeButtons fromRight:NO cellHeght:CELL_HEIGHT edge:edge];
  217. // 改变leftSwipeView的frame 使其显示在swipeImageView的最左端
  218. _leftSwipeView.frame = CGRectMake(-_leftSwipeView.frame.size.width, 0, _leftSwipeView.frame.size.width, CELL_HEIGHT);
  219. [self.swipeOverlayView addSubview:_leftSwipeView];
  220. }
  221. }
  222. /**
  223. * 判断滑动是否合法 并返回滑动距离
  224. */
  225. - (CGFloat)filterSwipeOffset:(CGFloat)offset
  226. {
  227. UIView *swipeView = offset > 0 ? self.leftSwipeView : self.rightSwipeView;
  228. if(!swipeView)
  229. {
  230. return 0.0;
  231. }
  232. else if(self.swipeStyle == SwipeTableCellStyleLeftToRight && offset < 0)
  233. {
  234. return 0.0;
  235. }
  236. else if(self.swipeStyle == SwipeTableCellStyleRightToLeft && offset > 0)
  237. {
  238. return 0.0;
  239. }
  240. return offset;
  241. }
  242. /**
  243. * 当滑动下一个cell时 取消上一个cell的滑动手势
  244. */
  245. - (void)cancelPanGesture
  246. {
  247. self.panGesture.enabled = NO;
  248. self.panGesture.enabled = YES;
  249. // 将上一个cell恢复原状
  250. if(self.swipeOffset){
  251. [self hiddenSwipeAnimationAtCell:YES];
  252. }
  253. }
  254. #pragma mark -- 处理点击手势
  255. - (void)handleTapGesture:(UITapGestureRecognizer *)tapGesture
  256. {
  257. BOOL hidden = YES;
  258. if([self.swipeDelegate respondsToSelector:@selector(tableView:hiddenSwipeViewWhenTapCellAtIndexPath:)])
  259. {
  260. // 判断点击cell是否隐藏swipeView
  261. hidden = [self.swipeDelegate tableView:self.tableView hiddenSwipeViewWhenTapCellAtIndexPath:[self.tableView indexPathForCell:self]];
  262. }
  263. if(hidden)
  264. {
  265. [self hiddenSwipeAnimationAtCell:YES];
  266. }
  267. }
  268. #pragma mark -- 处理手势动画效果
  269. /**
  270. * 隐藏滑动按钮 即将cell恢复原状
  271. *
  272. * @param isAnimation 是否隐藏
  273. */
  274. - (void)hiddenSwipeAnimationAtCell:(BOOL)isAnimation
  275. {
  276. SwipeView *aView = self.swipeOffset < 0 ? self.rightSwipeView : self.leftSwipeView;
  277. [self gestureAnimationWithOffset:isAnimation ? 0 : self.swipeOffset animationView:aView];
  278. }
  279. /**
  280. * 隐藏或显示滑动按钮的动画
  281. *
  282. * @param offset 滑动按钮的偏移量
  283. * @param animationView 右滑或左滑View
  284. */
  285. - (void)gestureAnimationWithOffset:(CGFloat)offset animationView:(SwipeView *)animationView
  286. {
  287. self.gestureAnimationSwipeView = animationView;
  288. if(self.dispalyLink){
  289. [self.dispalyLink invalidate];
  290. self.dispalyLink = nil;
  291. }
  292. if(offset !=0 ){
  293. [self createSwipeOverlayViewIfNeed];
  294. }
  295. if(!self.gestureAnimationSwipeView){
  296. self.swipeOffset = offset;
  297. return;
  298. }
  299. self.gestureAnimationSwipeView.from = self.swipeOffset;
  300. self.gestureAnimationSwipeView.to = offset;
  301. self.gestureAnimationSwipeView.start = 0;
  302. self.dispalyLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleAnimation:)];
  303. [self.dispalyLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
  304. }
  305. /**
  306. * 定时器处理动画
  307. */
  308. - (void)handleAnimation:(CADisplayLink *)link
  309. {
  310. if (!self.gestureAnimationSwipeView.start) {
  311. self.gestureAnimationSwipeView.start = link.timestamp;
  312. }
  313. CFTimeInterval elapsed = link.timestamp - self.gestureAnimationSwipeView.start;
  314. //滑动超过SwipeView的一半 自动显示或隐藏全部内容
  315. self.swipeOffset = [self.gestureAnimationSwipeView value:elapsed duration:self.gestureAnimationSwipeView.duration from:self.gestureAnimationSwipeView.from to:self.gestureAnimationSwipeView.to];
  316. if(elapsed >= self.gestureAnimationSwipeView.duration)
  317. {
  318. [link invalidate];
  319. self.dispalyLink = nil;
  320. }
  321. }
  322. #pragma mark -- UIGestureRecognizerDelegates
  323. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
  324. {
  325. if([gestureRecognizer isEqual:self.panGesture])
  326. {
  327. if(self.editing) return NO; // tableView在编辑状态
  328. if(self.targetOffset != 0.0) return YES; // 已经在滑动状态
  329. // 使UITableView可以滚动 解决滑动tableView和滑动cell冲突的问题
  330. CGPoint panPoint = [self.panGesture translationInView:self];
  331. if(fabs(panPoint.x) < fabs(panPoint.y))
  332. {
  333. for(SwipeTableCell *cell in self.tableView.visibleCells) // 滑动cell时,自动隐藏swipeView
  334. {
  335. if(cell.hideSwipeViewWhenScrollTableView && !cell.swipeOverlayView.hidden)
  336. {
  337. [cell hiddenSwipeAnimationAtCell:YES];
  338. }
  339. }
  340. return NO;
  341. }
  342. }
  343. else if(gestureRecognizer == self.tapGesture)
  344. {
  345. //解决和didSelect冲突问题
  346. CGPoint tapPoint = [self.tapGesture locationInView:self];
  347. //NSLog(@"%@,%@", NSStringFromCGRect(self.swipeOverlayView.frame), NSStringFromCGPoint(tapPoint));
  348. return CGRectContainsPoint(self.swipeImageView.frame, tapPoint);
  349. }
  350. return YES;
  351. }
  352. #pragma mark -- 获取滑动按钮、滑动按钮的样式
  353. /**
  354. * 获取滑动button的样式
  355. */
  356. - (void)getSwipeTableViewCellStyle
  357. {
  358. NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
  359. if([self.swipeDelegate respondsToSelector:@selector(tableView: styleOfSwipeButtonForRowAtIndexPath:)])
  360. {
  361. self.swipeStyle = [self.swipeDelegate tableView:self.tableView styleOfSwipeButtonForRowAtIndexPath:indexPath];
  362. }
  363. }
  364. /**
  365. * 获取滑动button
  366. */
  367. - (void)getSwipeButtons
  368. {
  369. NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
  370. if(self.swipeStyle == SwipeTableCellStyleRightToLeft)
  371. {
  372. if([self.swipeDelegate respondsToSelector:@selector(tableView: rightSwipeButtonsAtIndexPath:)])
  373. {
  374. self.rightSwipeButtons = [[self.swipeDelegate tableView:self.tableView rightSwipeButtonsAtIndexPath:indexPath] mutableCopy];
  375. }
  376. }
  377. else if(self.swipeStyle == SwipeTableCellStyleLeftToRight)
  378. {
  379. if([self.swipeDelegate respondsToSelector:@selector(tableView : leftSwipeButtonsAtIndexPath:)])
  380. {
  381. self.leftSwipeButtons = [self.swipeDelegate tableView:self.tableView leftSwipeButtonsAtIndexPath:indexPath];
  382. }
  383. }
  384. else if(self.swipeStyle == SwipeTableCellStyleBoth)
  385. {
  386. if([self.swipeDelegate respondsToSelector:@selector(tableView: rightSwipeButtonsAtIndexPath:)])
  387. {
  388. self.rightSwipeButtons = [self.swipeDelegate tableView:self.tableView rightSwipeButtonsAtIndexPath:indexPath];
  389. }
  390. if([self.swipeDelegate respondsToSelector:@selector(tableView : leftSwipeButtonsAtIndexPath:)])
  391. {
  392. self.leftSwipeButtons = [self.swipeDelegate tableView:self.tableView leftSwipeButtonsAtIndexPath:indexPath];
  393. }
  394. }
  395. }
  396. - (void)getSwipeViewTransformMode
  397. {
  398. if([self.swipeDelegate respondsToSelector:@selector(tableView:swipeViewTransformModeAtIndexPath:)])
  399. {
  400. self.transformMode = [self.swipeDelegate tableView:self.tableView swipeViewTransformModeAtIndexPath:[self.tableView indexPathForCell:self]];
  401. }
  402. }
  403. #pragma mark -- 私有方法
  404. /**
  405. * 截取平移过后的cell上的内容 以图片的形式显示出来
  406. */
  407. - (UIImage *)fecthTranslatedCellInfo:(UIView *)cell
  408. {
  409. UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
  410. [cell.layer renderInContext:UIGraphicsGetCurrentContext()];
  411. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  412. UIGraphicsEndImageContext();
  413. return image;
  414. }
  415. /** 删除所有子视图*/
  416. - (void)removeAllSubViewsAtView:(UIView *)view
  417. {
  418. while (view.subviews.count) {
  419. [[view.subviews lastObject] removeFromSuperview];
  420. }
  421. }
  422. #pragma mark -- 显示、隐藏cell上的内容
  423. /**
  424. * 显示self.swipeImageView
  425. */
  426. - (void)showSwipeOverlayViewIfNeed
  427. {
  428. if(self.isShowSwipeOverlayView) return;
  429. self.isShowSwipeOverlayView = YES;
  430. // 去除cell的选中状态,并保存
  431. self.selected = NO;
  432. self.previousSelectStyle = self.selectionStyle;
  433. self.selectionStyle = UITableViewCellSelectionStyleNone;
  434. // 显示swipeOverlayView,并将移动后cell上的内容裁剪到swipeImageView上
  435. self.swipeImageView.image = [self fecthTranslatedCellInfo:self];
  436. self.swipeOverlayView.hidden = NO;
  437. self.swipeImageView.userInteractionEnabled = YES;
  438. // 隐藏cell上的内容
  439. [self hiddenAccesoryViewAndContentOfCellIfNeed:YES];
  440. // 添加点击手势
  441. self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
  442. self.tapGesture.delegate = self;
  443. [self.swipeImageView addGestureRecognizer:self.tapGesture];
  444. }
  445. /**
  446. * 隐藏self.swipeImageView
  447. */
  448. - (void)hiddenSwipeOverlayViewIfNeed
  449. {
  450. if(!self.isShowSwipeOverlayView) return;
  451. self.isShowSwipeOverlayView = NO;
  452. // 隐藏swipeImageView
  453. self.swipeOverlayView.hidden = YES;
  454. self.swipeImageView.image = nil;
  455. self.swipeImageView.userInteractionEnabled = NO;
  456. // 若cell是选中状态 则滑动手势结束后还原cell的选中状态
  457. self.selectionStyle = self.previousSelectStyle;
  458. NSArray *selectCells = self.tableView.indexPathsForSelectedRows;
  459. if([selectCells containsObject:[self.tableView indexPathForCell:self]])
  460. {
  461. self.selected = NO;
  462. self.selected = YES;
  463. }
  464. // 将cell上的内容还原
  465. [self hiddenAccesoryViewAndContentOfCellIfNeed:NO];
  466. // 移除点击手势
  467. if(self.tapGesture){
  468. [self.swipeImageView removeGestureRecognizer:self.tapGesture];
  469. self.tapGesture = nil;
  470. }
  471. }
  472. /**
  473. * 是否隐藏accesoryView和cell上的内容,从而使得滑动cell时不会看见原有cell上的内容
  474. */
  475. - (void)hiddenAccesoryViewAndContentOfCellIfNeed:(BOOL)hidden
  476. {
  477. // 若只设置self.accessoryType 则不走这个判断语句
  478. if(self.accessoryView){
  479. self.accessoryView.hidden = hidden;
  480. }
  481. // 设置了self.accessoryType 其实是个UIButton
  482. for(UIView *subView in self.contentView.superview.subviews)
  483. {
  484. if(subView != self.contentView && ([subView isKindOfClass:[UIButton class]] || [NSStringFromClass(subView.class) rangeOfString:@"Disclosure"].location != NSNotFound))
  485. {
  486. subView.hidden = hidden;
  487. }
  488. }
  489. for(UIView *subView in self.contentView.superview.subviews)
  490. {
  491. if (subView == self.contentView) continue;
  492. // 若是cell上的subView则隐藏
  493. if(hidden && !subView.hidden)
  494. {
  495. subView.hidden = YES;
  496. [self.perviusHiddenViewSet addObject:subView];
  497. }
  498. // 还原cell时,将隐藏的cell上的内容显示出来
  499. else if(!hidden && [self.perviusHiddenViewSet containsObject:subView])
  500. {
  501. subView.hidden = NO;
  502. }
  503. }
  504. if(!hidden){
  505. [self.perviusHiddenViewSet removeAllObjects];
  506. }
  507. }
  508. #pragma mark -- getter或setter
  509. /**重写tableView的getter方法 获取cell所在的tableView*/
  510. - (UITableView *)tableView
  511. {
  512. if(_tableView){
  513. return _tableView;
  514. }
  515. // 获取当前cell所在的父tableView
  516. UIView *view = self.superview;
  517. while (view != nil)
  518. {
  519. if([view isKindOfClass:[UITableView class]])
  520. {
  521. _tableView = (UITableView *)view;
  522. }
  523. view = view.superview;
  524. }
  525. return _tableView;
  526. }
  527. /** 重写swipeOffset的setter方法 监测滑动手势*/
  528. - (void)setSwipeOffset:(CGFloat)swipeOffset
  529. {
  530. CGFloat sign = swipeOffset > 0 ? 1 : -1;
  531. SwipeView *currentSwipeView = swipeOffset < 0 ? self.rightSwipeView : self.leftSwipeView;
  532. _swipeOffset = swipeOffset;
  533. CGFloat offset = fabs(_swipeOffset);
  534. if(!currentSwipeView || offset == 0)
  535. {
  536. [self hiddenSwipeOverlayViewIfNeed];
  537. self.targetOffset = 0.0;
  538. return;
  539. }
  540. else
  541. {
  542. [self showSwipeOverlayViewIfNeed];
  543. self.targetOffset = offset > currentSwipeView.bounds.size.width*self.swipeThreshold ? currentSwipeView.bounds.size.width*sign : 0;
  544. }
  545. //NSLog(@"self.swipeOffset:%f", self.swipeOffset);
  546. // 平移swipeImageView,显示滑动后cell的内容
  547. self.swipeImageView.transform = CGAffineTransformMakeTranslation(self.swipeOffset, 0);
  548. SwipeView *viewArray[2] = {self.rightSwipeView, self.leftSwipeView};
  549. for (int i = 0; i< 2; i++)
  550. {
  551. SwipeView *swipeView = viewArray[i];
  552. if(!swipeView) continue;
  553. BOOL expand = self.isAllowExpand && offset > currentSwipeView.frame.size.width * self.expandThreshold;
  554. // 拉伸
  555. if (expand)
  556. {
  557. self.targetOffset = currentSwipeView.frame.size.width * sign;
  558. }
  559. else
  560. {
  561. // 平移显示按钮
  562. CGFloat translation = MIN(offset, currentSwipeView.bounds.size.width)*sign;
  563. swipeView.transform = CGAffineTransformMakeTranslation(translation, 0);
  564. if(currentSwipeView != swipeView) continue;
  565. [self getSwipeViewTransformMode];
  566. currentSwipeView.mode = self.transformMode;
  567. CGFloat t = MIN(1.0f, offset/currentSwipeView.bounds.size.width);
  568. // swipeView的弹出、隐藏动画效果
  569. [currentSwipeView swipeViewAnimationFromRight:self.swipeOffset<0 ? YES : NO effect:t cellHeight:CELL_HEIGHT];
  570. }
  571. }
  572. }
  573. #pragma mark -- expand
  574. - (void)expandToOffset:(CGFloat)offset
  575. {
  576. }
  577. #pragma mark -- 懒加载
  578. - (NSArray<SwipeButton *> *)leftSwipeButtons
  579. {
  580. if(!_leftSwipeButtons)
  581. {
  582. _leftSwipeButtons = [NSArray array];
  583. }
  584. return _leftSwipeButtons;
  585. }
  586. - (NSArray<SwipeButton *> *)rightSwipeButtons
  587. {
  588. if(!_rightSwipeButtons)
  589. {
  590. _rightSwipeButtons = [NSArray array];
  591. }
  592. return _rightSwipeButtons;
  593. }
  594. - (NSMutableSet *)perviusHiddenViewSet
  595. {
  596. if(!_perviusHiddenViewSet)
  597. {
  598. _perviusHiddenViewSet = [NSMutableSet set];
  599. }
  600. return _perviusHiddenViewSet;
  601. }
  602. @end