WBEmoticonInputView.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. //
  2. // WBStatusComposeEmoticonView.m
  3. // YYKitExample
  4. //
  5. // Created by ibireme on 15/9/6.
  6. // Copyright (C) 2015 ibireme. All rights reserved.
  7. //
  8. #import "WBEmoticonInputView.h"
  9. #import "WBStatusHelper.h"
  10. #import "WBModel.h"
  11. #import "YYKit.h"
  12. #define kViewHeight 216
  13. #define kToolbarHeight 37
  14. #define kOneEmoticonHeight 50
  15. #define kOnePageCount 20
  16. @interface WBEmoticonCell : UICollectionViewCell
  17. @property (nonatomic, strong) WBEmoticon *emoticon;
  18. @property (nonatomic, assign) BOOL isDelete;
  19. @property (nonatomic, strong) UIImageView *imageView;
  20. @end
  21. @implementation WBEmoticonCell
  22. - (instancetype)initWithFrame:(CGRect)frame {
  23. self = [super initWithFrame:frame];
  24. _imageView = [UIImageView new];
  25. _imageView.size = CGSizeMake(32, 32);
  26. _imageView.contentMode = UIViewContentModeScaleAspectFit;
  27. [self.contentView addSubview:_imageView];
  28. return self;
  29. }
  30. - (void)setEmoticon:(WBEmoticon *)emoticon {
  31. if (_emoticon == emoticon) return;
  32. _emoticon = emoticon;
  33. [self updateContent];
  34. }
  35. - (void)setIsDelete:(BOOL)isDelete {
  36. if (_isDelete == isDelete) return;
  37. _isDelete = isDelete;
  38. [self updateContent];
  39. }
  40. - (void)layoutSubviews {
  41. [super layoutSubviews];
  42. [self updateLayout];
  43. }
  44. - (void)updateContent {
  45. [_imageView cancelCurrentImageRequest];
  46. _imageView.image = nil;
  47. if (_isDelete) {
  48. _imageView.image = [WBStatusHelper imageNamed:@"compose_emotion_delete"];
  49. } else if (_emoticon) {
  50. if (_emoticon.type == WBEmoticonTypeEmoji) {
  51. NSNumber *num = [NSNumber numberWithString:_emoticon.code];
  52. NSString *str = [NSString stringWithUTF32Char:num.unsignedIntValue];
  53. if (str) {
  54. UIImage *img = [UIImage imageWithEmoji:str size:_imageView.width];
  55. _imageView.image = img;
  56. }
  57. } else if (_emoticon.group.groupID && _emoticon.png){
  58. NSString *pngPath = [[WBStatusHelper emoticonBundle] pathForScaledResource:_emoticon.png ofType:nil inDirectory:_emoticon.group.groupID];
  59. if (!pngPath) {
  60. NSString *addBundlePath = [[WBStatusHelper emoticonBundle].bundlePath stringByAppendingPathComponent:@"additional"];
  61. NSBundle *addBundle = [NSBundle bundleWithPath:addBundlePath];
  62. pngPath = [addBundle pathForScaledResource:_emoticon.png ofType:nil inDirectory:_emoticon.group.groupID];
  63. }
  64. if (pngPath) {
  65. [_imageView setImageWithURL:[NSURL fileURLWithPath:pngPath] options:YYWebImageOptionIgnoreDiskCache];
  66. }
  67. }
  68. }
  69. }
  70. - (void)updateLayout {
  71. _imageView.center = CGPointMake(self.width / 2, self.height / 2);
  72. }
  73. @end
  74. @protocol WBEmoticonScrollViewDelegate <UICollectionViewDelegate>
  75. - (void)emoticonScrollViewDidTapCell:(WBEmoticonCell *)cell;
  76. @end
  77. @interface WBEmoticonScrollView : UICollectionView
  78. @end
  79. @implementation WBEmoticonScrollView {
  80. NSTimeInterval *_touchBeganTime;
  81. BOOL _touchMoved;
  82. UIImageView *_magnifier;
  83. UIImageView *_magnifierContent;
  84. __weak WBEmoticonCell *_currentMagnifierCell;
  85. NSTimer *_backspaceTimer;
  86. }
  87. - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout {
  88. self = [super initWithFrame:frame collectionViewLayout:layout];
  89. self.backgroundColor = [UIColor clearColor];
  90. self.backgroundView = [UIView new];
  91. self.pagingEnabled = YES;
  92. self.showsHorizontalScrollIndicator = NO;
  93. self.clipsToBounds = NO;
  94. self.canCancelContentTouches = NO;
  95. self.multipleTouchEnabled = NO;
  96. _magnifier = [[UIImageView alloc] initWithImage:[WBStatusHelper imageNamed:@"emoticon_keyboard_magnifier"]];
  97. _magnifierContent = [UIImageView new];
  98. _magnifierContent.size = CGSizeMake(40, 40);
  99. _magnifierContent.centerX = _magnifier.width / 2;
  100. [_magnifier addSubview:_magnifierContent];
  101. _magnifier.hidden = YES;
  102. [self addSubview:_magnifier];
  103. return self;
  104. }
  105. - (void)dealloc {
  106. [self endBackspaceTimer];
  107. }
  108. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  109. _touchMoved = NO;
  110. WBEmoticonCell *cell = [self cellForTouches:touches];
  111. _currentMagnifierCell = cell;
  112. [self showMagnifierForCell:_currentMagnifierCell];
  113. if (cell.imageView.image && !cell.isDelete) {
  114. [[UIDevice currentDevice] playInputClick];
  115. }
  116. if (cell.isDelete) {
  117. [self endBackspaceTimer];
  118. [self performSelector:@selector(startBackspaceTimer) afterDelay:0.5];
  119. }
  120. }
  121. - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  122. _touchMoved = YES;
  123. if (_currentMagnifierCell && _currentMagnifierCell.isDelete) return;
  124. WBEmoticonCell *cell = [self cellForTouches:touches];
  125. if (cell != _currentMagnifierCell) {
  126. if (!_currentMagnifierCell.isDelete && !cell.isDelete) {
  127. _currentMagnifierCell = cell;
  128. }
  129. [self showMagnifierForCell:cell];
  130. }
  131. }
  132. - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  133. WBEmoticonCell *cell = [self cellForTouches:touches];
  134. if ((!_currentMagnifierCell.isDelete && cell.emoticon) || (!_touchMoved && cell.isDelete)) {
  135. if ([self.delegate respondsToSelector:@selector(emoticonScrollViewDidTapCell:)]) {
  136. [((id<WBEmoticonScrollViewDelegate>) self.delegate) emoticonScrollViewDidTapCell:cell];
  137. }
  138. }
  139. [self hideMagnifier];
  140. [self endBackspaceTimer];
  141. }
  142. - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  143. [self hideMagnifier];
  144. [self endBackspaceTimer];
  145. }
  146. - (WBEmoticonCell *)cellForTouches:(NSSet<UITouch *> *)touches {
  147. UITouch *touch = touches.anyObject;
  148. CGPoint point = [touch locationInView:self];
  149. NSIndexPath *indexPath = [self indexPathForItemAtPoint:point];
  150. if (indexPath) {
  151. WBEmoticonCell *cell = (id)[self cellForItemAtIndexPath:indexPath];
  152. return cell;
  153. }
  154. return nil;
  155. }
  156. - (void)showMagnifierForCell:(WBEmoticonCell *)cell {
  157. if (cell.isDelete || !cell.imageView.image) {
  158. [self hideMagnifier];
  159. return;
  160. }
  161. CGRect rect = [cell convertRect:cell.bounds toView:self];
  162. _magnifier.centerX = CGRectGetMidX(rect);
  163. _magnifier.bottom = CGRectGetMaxY(rect) - 9;
  164. _magnifier.hidden = NO;
  165. _magnifierContent.image = cell.imageView.image;
  166. _magnifierContent.top = 20;
  167. [_magnifierContent.layer removeAllAnimations];
  168. NSTimeInterval dur = 0.1;
  169. [UIView animateWithDuration:dur delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  170. _magnifierContent.top = 3;
  171. } completion:^(BOOL finished) {
  172. [UIView animateWithDuration:dur delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  173. _magnifierContent.top = 6;
  174. } completion:^(BOOL finished) {
  175. [UIView animateWithDuration:dur delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  176. _magnifierContent.top = 5;
  177. } completion:^(BOOL finished) {
  178. }];
  179. }];
  180. }];
  181. }
  182. - (void)hideMagnifier {
  183. _magnifier.hidden = YES;
  184. }
  185. - (void)startBackspaceTimer {
  186. [self endBackspaceTimer];
  187. @weakify(self);
  188. _backspaceTimer = [NSTimer timerWithTimeInterval:0.1 block:^(NSTimer *timer) {
  189. @strongify(self);
  190. if (!self) return;
  191. WBEmoticonCell *cell = self->_currentMagnifierCell;
  192. if (cell.isDelete) {
  193. if ([self.delegate respondsToSelector:@selector(emoticonScrollViewDidTapCell:)]) {
  194. [[UIDevice currentDevice] playInputClick];
  195. [((id<WBEmoticonScrollViewDelegate>) self.delegate) emoticonScrollViewDidTapCell:cell];
  196. }
  197. }
  198. } repeats:YES];
  199. [[NSRunLoop mainRunLoop] addTimer:_backspaceTimer forMode:NSRunLoopCommonModes];
  200. }
  201. - (void)endBackspaceTimer {
  202. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startBackspaceTimer) object:nil];
  203. [_backspaceTimer invalidate];
  204. _backspaceTimer = nil;
  205. }
  206. @end
  207. @interface WBEmoticonInputView () <UICollectionViewDelegate, UICollectionViewDataSource, UIInputViewAudioFeedback,WBEmoticonScrollViewDelegate>
  208. @property (nonatomic, strong) NSArray<UIButton *> *toolbarButtons;
  209. @property (nonatomic, strong) UICollectionView *collectionView;
  210. @property (nonatomic, strong) UIView *pageControl;
  211. @property (nonatomic, strong) NSArray<WBEmoticonGroup *> *emoticonGroups;
  212. @property (nonatomic, strong) NSArray<NSNumber *> *emoticonGroupPageIndexs;
  213. @property (nonatomic, strong) NSArray<NSNumber *> *emoticonGroupPageCounts;
  214. @property (nonatomic, assign) NSInteger emoticonGroupTotalPageCount;
  215. @property (nonatomic, assign) NSInteger currentPageIndex;
  216. @end
  217. @implementation WBEmoticonInputView
  218. + (instancetype)sharedView {
  219. static WBEmoticonInputView *v;
  220. static dispatch_once_t onceToken;
  221. dispatch_once(&onceToken, ^{
  222. v = [self new];
  223. });
  224. return v;
  225. }
  226. - (instancetype)init {
  227. self = [super init];
  228. self.frame = CGRectMake(0, 0, kScreenWidth, kViewHeight);
  229. self.backgroundColor = UIColorHex(f9f9f9);
  230. [self _initGroups];
  231. [self _initTopLine];
  232. [self _initCollectionView];
  233. [self _initToolbar];
  234. _currentPageIndex = NSNotFound;
  235. [self _toolbarBtnDidTapped:_toolbarButtons.firstObject];
  236. return self;
  237. }
  238. - (void)_initGroups {
  239. _emoticonGroups = [WBStatusHelper emoticonGroups];
  240. NSMutableArray *indexs = [NSMutableArray new];
  241. NSUInteger index = 0;
  242. for (WBEmoticonGroup *group in _emoticonGroups) {
  243. [indexs addObject:@(index)];
  244. NSUInteger count = ceil(group.emoticons.count / (float)kOnePageCount);
  245. if (count == 0) count = 1;
  246. index += count;
  247. }
  248. _emoticonGroupPageIndexs = indexs;
  249. NSMutableArray *pageCounts = [NSMutableArray new];
  250. _emoticonGroupTotalPageCount = 0;
  251. for (WBEmoticonGroup *group in _emoticonGroups) {
  252. NSUInteger pageCount = ceil(group.emoticons.count / (float)kOnePageCount);
  253. if (pageCount == 0) pageCount = 1;
  254. [pageCounts addObject:@(pageCount)];
  255. _emoticonGroupTotalPageCount += pageCount;
  256. }
  257. _emoticonGroupPageCounts = pageCounts;
  258. }
  259. - (void)_initTopLine {
  260. UIView *line = [UIView new];
  261. line.width = self.width;
  262. line.height = CGFloatFromPixel(1);
  263. line.backgroundColor = UIColorHex(bfbfbf);
  264. line.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  265. [self addSubview:line];
  266. }
  267. - (void)_initCollectionView {
  268. CGFloat itemWidth = (kScreenWidth - 10 * 2) / 7.0;
  269. itemWidth = CGFloatPixelRound(itemWidth);
  270. CGFloat padding = (kScreenWidth - 7 * itemWidth) / 2.0;
  271. CGFloat paddingLeft = CGFloatPixelRound(padding);
  272. CGFloat paddingRight = kScreenWidth - paddingLeft - itemWidth * 7;
  273. UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
  274. layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  275. layout.itemSize = CGSizeMake(itemWidth, kOneEmoticonHeight);
  276. layout.minimumLineSpacing = 0;
  277. layout.minimumInteritemSpacing = 0;
  278. layout.sectionInset = UIEdgeInsetsMake(0, paddingLeft, 0, paddingRight);
  279. _collectionView = [[WBEmoticonScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kOneEmoticonHeight * 3) collectionViewLayout:layout];
  280. [_collectionView registerClass:[WBEmoticonCell class] forCellWithReuseIdentifier:@"cell"];
  281. _collectionView.delegate = self;
  282. _collectionView.dataSource = self;
  283. _collectionView.top = 5;
  284. [self addSubview:_collectionView];
  285. _pageControl = [UIView new];
  286. _pageControl.size = CGSizeMake(kScreenWidth, 20);
  287. _pageControl.top = _collectionView.bottom - 5;
  288. _pageControl.userInteractionEnabled = NO;
  289. [self addSubview:_pageControl];
  290. }
  291. - (void)_initToolbar {
  292. UIView *toolbar = [UIView new];
  293. toolbar.size = CGSizeMake(kScreenWidth, kToolbarHeight);
  294. UIImageView *bg = [[UIImageView alloc] initWithImage:[WBStatusHelper imageNamed:@"compose_emotion_table_right_normal"]];
  295. bg.size = toolbar.size;
  296. [toolbar addSubview:bg];
  297. UIScrollView *scroll = [UIScrollView new];
  298. scroll.showsHorizontalScrollIndicator = NO;
  299. scroll.alwaysBounceHorizontal = YES;
  300. scroll.size = toolbar.size;
  301. scroll.contentSize = toolbar.size;
  302. [toolbar addSubview:scroll];
  303. NSMutableArray *btns = [NSMutableArray new];
  304. UIButton *btn;
  305. for (NSUInteger i = 0; i < _emoticonGroups.count; i++) {
  306. WBEmoticonGroup *group = _emoticonGroups[i];
  307. btn = [self _createToolbarButton];
  308. [btn setTitle:group.nameCN forState:UIControlStateNormal];
  309. btn.left = kScreenWidth / (float)_emoticonGroups.count * i;
  310. btn.tag = i;
  311. [scroll addSubview:btn];
  312. [btns addObject:btn];
  313. }
  314. toolbar.bottom = self.height;
  315. [self addSubview:toolbar];
  316. _toolbarButtons = btns;
  317. }
  318. - (UIButton *)_createToolbarButton {
  319. UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
  320. btn.exclusiveTouch = YES;
  321. btn.size = CGSizeMake(kScreenWidth / _emoticonGroups.count, kToolbarHeight);
  322. btn.titleLabel.font = [UIFont systemFontOfSize:14];
  323. [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  324. [btn setTitleColor:UIColorHex(5D5C5A) forState:UIControlStateSelected];
  325. UIImage *img;
  326. img = [WBStatusHelper imageNamed:@"compose_emotion_table_left_normal"];
  327. img = [img resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, img.size.width - 1) resizingMode:UIImageResizingModeStretch];
  328. [btn setBackgroundImage:img forState:UIControlStateNormal];
  329. img = [WBStatusHelper imageNamed:@"compose_emotion_table_left_selected"];
  330. img = [img resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, img.size.width - 1) resizingMode:UIImageResizingModeStretch];
  331. [btn setBackgroundImage:img forState:UIControlStateSelected];
  332. [btn addTarget:self action:@selector(_toolbarBtnDidTapped:) forControlEvents:UIControlEventTouchUpInside];
  333. return btn;
  334. }
  335. - (void)_toolbarBtnDidTapped:(UIButton *)btn {
  336. NSInteger groupIndex = btn.tag;
  337. NSInteger page = ((NSNumber *)_emoticonGroupPageIndexs[groupIndex]).integerValue;
  338. CGRect rect = CGRectMake(page * _collectionView.width, 0, _collectionView.width, _collectionView.height);
  339. [_collectionView scrollRectToVisible:rect animated:NO];
  340. [self scrollViewDidScroll:_collectionView];
  341. }
  342. - (WBEmoticon *)_emoticonForIndexPath:(NSIndexPath *)indexPath {
  343. NSUInteger section = indexPath.section;
  344. for (NSInteger i = _emoticonGroupPageIndexs.count - 1; i >= 0; i--) {
  345. NSNumber *pageIndex = _emoticonGroupPageIndexs[i];
  346. if (section >= pageIndex.unsignedIntegerValue) {
  347. WBEmoticonGroup *group = _emoticonGroups[i];
  348. NSUInteger page = section - pageIndex.unsignedIntegerValue;
  349. NSUInteger index = page * kOnePageCount + indexPath.row;
  350. // transpose line/row
  351. NSUInteger ip = index / kOnePageCount;
  352. NSUInteger ii = index % kOnePageCount;
  353. NSUInteger reIndex = (ii % 3) * 7 + (ii / 3);
  354. index = reIndex + ip * kOnePageCount;
  355. if (index < group.emoticons.count) {
  356. return group.emoticons[index];
  357. } else {
  358. return nil;
  359. }
  360. }
  361. }
  362. return nil;
  363. }
  364. #pragma mark WBEmoticonScrollViewDelegate
  365. - (void)emoticonScrollViewDidTapCell:(WBEmoticonCell *)cell {
  366. if (!cell) return;
  367. if (cell.isDelete) {
  368. if ([self.delegate respondsToSelector:@selector(emoticonInputDidTapBackspace)]) {
  369. [[UIDevice currentDevice] playInputClick];
  370. [self.delegate emoticonInputDidTapBackspace];
  371. }
  372. } else if (cell.emoticon) {
  373. NSString *text = nil;
  374. switch (cell.emoticon.type) {
  375. case WBEmoticonTypeImage: {
  376. text = cell.emoticon.chs;
  377. } break;
  378. case WBEmoticonTypeEmoji: {
  379. NSNumber *num = [NSNumber numberWithString:cell.emoticon.code];
  380. text = [NSString stringWithUTF32Char:num.unsignedIntValue];
  381. } break;
  382. default:break;
  383. }
  384. if (text && [self.delegate respondsToSelector:@selector(emoticonInputDidTapText:)]) {
  385. [self.delegate emoticonInputDidTapText:text];
  386. }
  387. }
  388. }
  389. #pragma mark UICollectionViewDelegate
  390. - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  391. NSInteger page = round(scrollView.contentOffset.x / scrollView.width);
  392. if (page < 0) page = 0;
  393. else if (page >= _emoticonGroupTotalPageCount) page = _emoticonGroupTotalPageCount - 1;
  394. if (page == _currentPageIndex) return;
  395. _currentPageIndex = page;
  396. NSInteger curGroupIndex = 0, curGroupPageIndex = 0, curGroupPageCount = 0;
  397. for (NSInteger i = _emoticonGroupPageIndexs.count - 1; i >= 0; i--) {
  398. NSNumber *pageIndex = _emoticonGroupPageIndexs[i];
  399. if (page >= pageIndex.unsignedIntegerValue) {
  400. curGroupIndex = i;
  401. curGroupPageIndex = ((NSNumber *)_emoticonGroupPageIndexs[i]).integerValue;
  402. curGroupPageCount = ((NSNumber *)_emoticonGroupPageCounts[i]).integerValue;
  403. break;
  404. }
  405. }
  406. [_pageControl.layer removeAllSublayers];
  407. CGFloat padding = 5, width = 6, height = 2;
  408. CGFloat pageControlWidth = (width + 2 * padding) * curGroupPageCount;
  409. for (NSInteger i = 0; i < curGroupPageCount; i++) {
  410. CALayer *layer = [CALayer layer];
  411. layer.size = CGSizeMake(width, height);
  412. layer.cornerRadius = 1;
  413. if (page - curGroupPageIndex == i) {
  414. layer.backgroundColor = UIColorHex(fd8225).CGColor;
  415. } else {
  416. layer.backgroundColor = UIColorHex(dedede).CGColor;
  417. }
  418. layer.centerY = _pageControl.height / 2;
  419. layer.left = (_pageControl.width - pageControlWidth) / 2 + i * (width + 2 * padding) + padding;
  420. [_pageControl.layer addSublayer:layer];
  421. }
  422. [_toolbarButtons enumerateObjectsUsingBlock:^(UIButton *btn, NSUInteger idx, BOOL *stop) {
  423. btn.selected = (idx == curGroupIndex);
  424. }];
  425. }
  426. - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
  427. return NO;
  428. }
  429. - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  430. return NO;
  431. }
  432. #pragma mark UICollectionViewDataSource
  433. - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
  434. return _emoticonGroupTotalPageCount;
  435. }
  436. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  437. return kOnePageCount + 1;
  438. }
  439. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  440. WBEmoticonCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
  441. if (indexPath.row == kOnePageCount) {
  442. cell.isDelete = YES;
  443. cell.emoticon = nil;
  444. } else {
  445. cell.isDelete = NO;
  446. cell.emoticon = [self _emoticonForIndexPath:indexPath];
  447. }
  448. return cell;
  449. }
  450. #pragma mark - UIInputViewAudioFeedback
  451. - (BOOL)enableInputClicksWhenVisible {
  452. return YES;
  453. }
  454. @end