EMChatBar.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. //
  2. // EMChatBar.m
  3. // ChatDemo-UI3.0
  4. //
  5. // Created by XieYajie on 2019/1/25.
  6. // Copyright © 2019 XieYajie. All rights reserved.
  7. //
  8. #import "EMChatBar.h"
  9. #import "AudioShowView.h"
  10. #import "SmartBarModel.h"
  11. #import "NoticeNewGroupMenuCell.h"
  12. #define ktextViewMinHeight 40
  13. #define ktextViewMaxHeight 120
  14. @interface EMChatBar()<UITextViewDelegate,UICollectionViewDelegate,UICollectionViewDataSource>
  15. @property (nonatomic) CGFloat version;
  16. @property (nonatomic) CGFloat previousTextViewContentHeight;
  17. @property (nonatomic) CGFloat keyHeight;
  18. @property (nonatomic) CGFloat cusviewHeight;
  19. @property (nonatomic, strong) UIButton *selectedButton;
  20. @property (nonatomic, strong) UIButton *speakBtn;
  21. @property (nonatomic, strong) UIButton *audioButton;
  22. @property (nonatomic, strong) UIButton *moreButton;
  23. @property (nonatomic, strong) UIButton *emojiButton;
  24. @property (nonatomic, strong) UIView *currentMoreView;
  25. @property (nonatomic, copy) NSMutableArray * listArray;
  26. @property (strong,nonatomic) UICollectionView *collectionView;
  27. @property (nonatomic, assign) BOOL isInput;
  28. @end
  29. @implementation EMChatBar
  30. - (instancetype)init
  31. {
  32. self = [super init];
  33. if (self) {
  34. _version = [[[UIDevice currentDevice] systemVersion] floatValue];
  35. _previousTextViewContentHeight = ktextViewMinHeight;
  36. [self _setupSubviews];
  37. }
  38. return self;
  39. }
  40. #pragma mark - Subviews
  41. - (void)_setupSubviews
  42. {
  43. self.keyHeight = 56;
  44. self.cusviewHeight = 0;
  45. self.backgroundColor = UIColorHex(f5f5f5);
  46. UIView *line = [[UIView alloc] init];
  47. line.backgroundColor = UIColorHex(E4E4E4);
  48. [self addSubview:line];
  49. [line mas_makeConstraints:^(MASConstraintMaker *make) {
  50. make.top.left.right.equalTo(self);
  51. make.height.equalTo(@0.5);
  52. }];
  53. self.textView = [[EMTextView alloc] init];
  54. self.textView.delegate = self;
  55. self.textView.placeholder = @"";
  56. self.textView.font = [UIFont systemFontOfSize:16];
  57. self.textView.returnKeyType = UIReturnKeySend;
  58. self.textView.backgroundColor = [UIColor whiteColor];
  59. self.textView.layer.cornerRadius = 5.f;
  60. self.textView.layer.masksToBounds = YES;
  61. [self addSubview:self.textView];
  62. [self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
  63. make.top.equalTo(self.mas_top).offset(8);
  64. make.height.mas_equalTo(ktextViewMinHeight);
  65. make.left.equalTo(self.mas_left).offset(57);
  66. make.right.equalTo(self.mas_right).offset(-99);
  67. }];
  68. self.audioButton = [[UIButton alloc] init];
  69. [self.audioButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_yy_icon"] forState:UIControlStateNormal];
  70. [self.audioButton addTarget:self action:@selector(audioButtonAction:) forControlEvents:UIControlEventTouchUpInside];
  71. [self addSubview:self.audioButton];
  72. [self.audioButton mas_makeConstraints:^(MASConstraintMaker *make) {
  73. make.bottom.mas_equalTo(self.textView.mas_bottom).mas_offset(-6.5);
  74. // make.centerY.equalTo(self.textView.mas_centerY);
  75. make.left.mas_offset(15);
  76. make.size.mas_offset(CGSizeMake(27, 27));
  77. }];
  78. self.moreButton = [[UIButton alloc] init];
  79. [self.moreButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_add_icon"] forState:UIControlStateNormal];
  80. [self.moreButton addTarget:self action:@selector(moreButtonAction:) forControlEvents:UIControlEventTouchUpInside];
  81. [self addSubview:self.moreButton];
  82. [self.moreButton mas_makeConstraints:^(MASConstraintMaker *make) {
  83. // make.centerY.equalTo(self.textView.mas_centerY);
  84. make.bottom.mas_equalTo(self.textView.mas_bottom).mas_offset(-6.5);
  85. make.right.mas_offset(-15);
  86. make.size.mas_offset(CGSizeMake(27, 27));
  87. }];
  88. self.emojiButton = [[UIButton alloc] init];
  89. [self.emojiButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_bq_icon"] forState:UIControlStateNormal];
  90. [self.emojiButton addTarget:self action:@selector(emoticonButtonAction:) forControlEvents:UIControlEventTouchUpInside];
  91. [self addSubview:self.emojiButton];
  92. [self.emojiButton mas_makeConstraints:^(MASConstraintMaker *make) {
  93. // make.centerY.equalTo(self.textView.mas_centerY);
  94. make.bottom.mas_equalTo(self.textView.mas_bottom).mas_offset(-6.5);
  95. make.right.equalTo(self.moreButton.mas_left).offset(-15);
  96. make.size.mas_offset(CGSizeMake(27, 27));
  97. }];
  98. self.speakBtn = [[UIButton alloc] init];
  99. NSMutableAttributedString *startstring = [[NSMutableAttributedString alloc] initWithString:@"按住 说话" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"PingFang SC" size: 17],NSForegroundColorAttributeName: [UIColor colorWithRed:10/255.0 green:10/255.0 blue:10/255.0 alpha:1.0]}];
  100. NSMutableAttributedString *endstring = [[NSMutableAttributedString alloc] initWithString:@"松开 结束" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"PingFang SC" size: 17],NSForegroundColorAttributeName: [UIColor colorWithRed:10/255.0 green:10/255.0 blue:10/255.0 alpha:1.0]}];
  101. [self.speakBtn setAttributedTitle:startstring forState:UIControlStateNormal];
  102. [self.speakBtn setAttributedTitle:endstring forState:UIControlStateHighlighted];
  103. self.speakBtn.backgroundColor = [UIColor whiteColor];
  104. self.speakBtn.layer.cornerRadius = 5.f;
  105. self.speakBtn.layer.masksToBounds = YES;
  106. [self addSubview:self.speakBtn];
  107. [self.speakBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  108. make.edges.mas_equalTo(self.textView);
  109. }];
  110. self.speakBtn.hidden = YES;
  111. UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
  112. longPress.minimumPressDuration = 0;
  113. [self.speakBtn addGestureRecognizer:longPress];
  114. }
  115. - (void)longPress:(UILongPressGestureRecognizer *)gestureRecognizer
  116. {
  117. CGPoint point = [gestureRecognizer locationInView:self];
  118. NSMutableAttributedString *startstring = [[NSMutableAttributedString alloc] initWithString:@"按住 说话" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"PingFang SC" size: 17],NSForegroundColorAttributeName: [UIColor colorWithRed:10/255.0 green:10/255.0 blue:10/255.0 alpha:1.0]}];
  119. NSMutableAttributedString *endstring = [[NSMutableAttributedString alloc] initWithString:@"松开 发送" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"PingFang SC" size: 17],NSForegroundColorAttributeName: [UIColor colorWithRed:10/255.0 green:10/255.0 blue:10/255.0 alpha:1.0]}];
  120. if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
  121. [self.speakBtn setAttributedTitle:endstring forState:UIControlStateNormal];
  122. if (self.recordAudioView) {
  123. [[AudioShowView sharedAudioShowView] show];
  124. [self.recordAudioView _startRecord];
  125. [AudioShowView sharedAudioShowView].recorder = [self.recordAudioView getRecorder];
  126. }
  127. } else if(gestureRecognizer.state == UIGestureRecognizerStateEnded) {
  128. [self.speakBtn setAttributedTitle:startstring forState:UIControlStateNormal];
  129. if (self.recordAudioView) {
  130. [[AudioShowView sharedAudioShowView] dismiss];
  131. [self.recordAudioView _stopRecord];
  132. }
  133. } else if(gestureRecognizer.state == UIGestureRecognizerStateChanged) {
  134. if (![self.speakBtn.layer containsPoint:point]) {
  135. [self.speakBtn setAttributedTitle:endstring forState:UIControlStateNormal];
  136. if (self.recordAudioView) {
  137. [[AudioShowView sharedAudioShowView] dismiss];
  138. [self.recordAudioView _cancelRecord];
  139. }
  140. }
  141. } else if (gestureRecognizer.state == UIGestureRecognizerStateFailed) {
  142. NSLog(@"失败");
  143. } else if (gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
  144. NSLog(@"取消");
  145. }
  146. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBarDidShowMoreViewAction:)]) {
  147. [self.delegate chatBarDidShowMoreViewAction:NO];
  148. }
  149. }
  150. - (void)clearAllView
  151. {
  152. [self.emojiButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_bq_icon"] forState:UIControlStateNormal];
  153. [self.audioButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_yy_icon"] forState:UIControlStateNormal];
  154. [self.moreButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_add_icon"] forState:UIControlStateNormal];
  155. self.speakBtn.hidden = YES;
  156. self.textView.hidden = NO;
  157. }
  158. #pragma mark - UITextViewDelegate
  159. - (BOOL)textViewShouldBeginEditing:(UITextView *)textView
  160. {
  161. if (self.currentMoreView) {
  162. [self clearAllView];
  163. [self.currentMoreView removeFromSuperview];
  164. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  165. make.height.mas_equalTo(self.keyHeight);
  166. }];
  167. }
  168. for (UIButton *button in self.buttonArray) {
  169. if (button.isSelected) {
  170. button.selected = NO;
  171. break;
  172. }
  173. }
  174. return YES;
  175. }
  176. - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
  177. {
  178. if (self.delegate && [self.delegate respondsToSelector:@selector(inputView:shouldChangeTextInRange:replacementText:)]) {
  179. return [self.delegate inputView:self.textView shouldChangeTextInRange:range replacementText:text];
  180. }
  181. return YES;
  182. }
  183. - (void)textViewDidChange:(UITextView *)textView
  184. {
  185. [self _updatetextViewHeight];
  186. if (self.delegate && [self.delegate respondsToSelector:@selector(inputViewDidChange:)]) {
  187. [self.delegate inputViewDidChange:self.textView];
  188. }
  189. }
  190. #pragma mark - Private
  191. - (CGFloat)_gettextViewContontHeight
  192. {
  193. if (self.version >= 7.0) {
  194. return ceilf([self.textView sizeThatFits:self.textView.frame.size].height);
  195. } else {
  196. return self.textView.contentSize.height;
  197. }
  198. }
  199. - (void)_updatetextViewHeight
  200. {
  201. CGFloat height = [self _gettextViewContontHeight];
  202. if (height < ktextViewMinHeight) {
  203. height = ktextViewMinHeight;
  204. }
  205. if (height > ktextViewMaxHeight) {
  206. height = ktextViewMaxHeight;
  207. }
  208. self.keyHeight = height + 16;
  209. if (height == self.previousTextViewContentHeight) {
  210. return;
  211. }
  212. self.previousTextViewContentHeight = height;
  213. [self.textView mas_updateConstraints:^(MASConstraintMaker *make) {
  214. make.height.mas_equalTo(height);
  215. }];
  216. if (self.currentMoreView) {
  217. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  218. make.height.mas_equalTo(self.keyHeight + self.cusviewHeight);
  219. }];
  220. }else{
  221. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  222. make.height.mas_equalTo(self.keyHeight);
  223. }];
  224. }
  225. }
  226. #pragma mark - Public
  227. - (void)clearInputViewText
  228. {
  229. self.textView.text = @"";
  230. [self _updatetextViewHeight];
  231. }
  232. - (void)inputViewAppendText:(NSString *)aText
  233. {
  234. if ([aText length] > 0) {
  235. self.textView.text = [NSString stringWithFormat:@"%@%@", self.textView.text, aText];
  236. [self _updatetextViewHeight];
  237. }
  238. }
  239. - (void)clearMoreViewAndSelectedButton
  240. {
  241. if (self.currentMoreView) {
  242. [self.currentMoreView removeFromSuperview];
  243. self.currentMoreView = nil;
  244. [self clearAllView];
  245. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  246. make.height.mas_equalTo(self.keyHeight);
  247. }];
  248. }
  249. if (self.selectedButton) {
  250. self.selectedButton.selected = NO;
  251. self.selectedButton = nil;
  252. }
  253. }
  254. #pragma mark - Action
  255. - (void)_buttonAction:(UIButton *)aButton
  256. {
  257. [self.textView resignFirstResponder];
  258. aButton.selected = !aButton.selected;
  259. if (self.currentMoreView) {
  260. [self.currentMoreView removeFromSuperview];
  261. self.currentMoreView = nil;
  262. }
  263. if (self.selectedButton != aButton) {
  264. self.selectedButton.selected = NO;
  265. self.selectedButton = nil;
  266. self.selectedButton = aButton;
  267. } else {
  268. self.selectedButton = nil;
  269. }
  270. if (aButton.selected) {
  271. self.selectedButton = aButton;
  272. }
  273. [self clearAllView];
  274. }
  275. - (void)audioButtonAction:(UIButton *)aButton
  276. {
  277. [self _buttonAction:aButton];
  278. [self.textView mas_updateConstraints:^(MASConstraintMaker *make) {
  279. make.height.mas_equalTo(@40);
  280. }];
  281. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  282. make.height.mas_equalTo(@56);
  283. }];
  284. if (aButton.selected) {
  285. [aButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_jp_icon"] forState:UIControlStateNormal];
  286. self.textView.hidden = YES;
  287. self.speakBtn.hidden = NO;
  288. }else{
  289. [aButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_yy_icon"] forState:UIControlStateNormal];
  290. self.speakBtn.hidden = YES;
  291. self.textView.hidden = NO;
  292. [self.textView becomeFirstResponder];
  293. }
  294. }
  295. - (void)emoticonButtonAction:(UIButton *)aButton
  296. {
  297. [self _buttonAction:aButton];
  298. if (aButton.selected) {
  299. [aButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_jp_icon"] forState:UIControlStateNormal];
  300. if (self.moreEmoticonView) {
  301. self.currentMoreView = self.moreEmoticonView;
  302. [self addSubview:self.moreEmoticonView];
  303. [self.moreEmoticonView mas_makeConstraints:^(MASConstraintMaker *make) {
  304. make.left.equalTo(self);
  305. make.right.equalTo(self);
  306. if (@available(iOS 11.0, *)) {
  307. make.bottom.equalTo(self.mas_safeAreaLayoutGuideBottom);
  308. } else {
  309. make.bottom.equalTo(self.mas_bottom);
  310. }
  311. make.height.mas_equalTo(self.moreEmoticonView.viewHeight);
  312. }];
  313. self.cusviewHeight = self.moreEmoticonView.viewHeight;
  314. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  315. make.height.mas_equalTo(self.keyHeight + self.cusviewHeight);
  316. }];
  317. }
  318. }else{
  319. [aButton setImage:[UIImage imageNamed:@"chatmsg_detailchat_bq_icon"] forState:UIControlStateNormal];
  320. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  321. make.height.mas_equalTo(self.keyHeight);
  322. }];
  323. [self.textView becomeFirstResponder];
  324. }
  325. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBarDidShowMoreViewAction:)]) {
  326. [self.delegate chatBarDidShowMoreViewAction:NO];
  327. }
  328. }
  329. //更多
  330. - (void)moreButtonAction:(UIButton *)aButton
  331. {
  332. [self _buttonAction:aButton];
  333. [self addSubview:self.collectionView];
  334. [self CreatelistView];
  335. self.currentMoreView = self.collectionView;
  336. [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
  337. make.left.equalTo(self);
  338. make.top.equalTo(self.textView.mas_bottom).offset(8);
  339. make.right.equalTo(self);
  340. if (@available(iOS 11.0, *)) {
  341. make.bottom.equalTo(self.mas_safeAreaLayoutGuideBottom);
  342. } else {
  343. make.bottom.equalTo(self.mas_bottom);
  344. }
  345. }];
  346. if (self.cusviewHeight > 0) {
  347. self.collectionView.hidden = YES;
  348. [self.textView becomeFirstResponder];
  349. self.cusviewHeight = 0;
  350. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBarDidShowMoreViewAction:)]) {
  351. [self.delegate chatBarDidShowMoreViewAction:YES];
  352. }
  353. // [self.collectionView mas_updateConstraints:^(MASConstraintMaker *make) {
  354. // make.height.mas_equalTo(self.cusviewHeight);
  355. // }];
  356. }else{
  357. self.collectionView.hidden = NO;
  358. self.cusviewHeight = 215.f * HEIGHT_SCALE;
  359. if (self.delegate && [self.delegate respondsToSelector:@selector(chatBarDidShowMoreViewAction:)]) {
  360. [self.delegate chatBarDidShowMoreViewAction:NO];
  361. }
  362. // [self.collectionView mas_updateConstraints:^(MASConstraintMaker *make) {
  363. // make.height.mas_equalTo(self.cusviewHeight);
  364. // }];
  365. }
  366. [self mas_updateConstraints:^(MASConstraintMaker *make) {
  367. make.height.mas_equalTo(self.keyHeight + self.cusviewHeight);
  368. }];
  369. }
  370. - (void)CreatelistView
  371. {
  372. [self.listArray removeAllObjects];
  373. NSArray * array = @[@{@"name":@"图片",@"image":@"chatmsg_notice_photo_icon",@"type":@(0)},
  374. @{@"name":@"拍摄",@"image":@"chatmsg_notice_xiangji_icon",@"type":@(1)},
  375. @{@"name":@"我的笔记",@"image":@"chatmsg_notice_biji_icon",@"type":@(2)},
  376. @{@"name":@"我的收藏",@"image":@"chatmsg_notice_sc_icon",@"type":@(3)},
  377. @{@"name":@"文件",@"image":@"chatmsg_notice_file_icon",@"type":@(4)}];
  378. for (NSDictionary * dict in array) {
  379. SmartBarModel * model = [[SmartBarModel alloc] init];
  380. model.name = [dict objectForKey:@"name"];
  381. model.image = [dict objectForKey:@"image"];
  382. model.type = [[dict objectForKey:@"type"] intValue];
  383. [self.listArray addObject:model];
  384. }
  385. [self.collectionView reloadData];
  386. }
  387. #pragma mark - UICollectionView
  388. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  389. return self.listArray.count;
  390. }
  391. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
  392. {
  393. SmartBarModel * model = [self.listArray objectAtIndex:indexPath.item];
  394. NoticeNewGroupMenuCell *cell = [ collectionView dequeueReusableCellWithReuseIdentifier:@"NoticeNewGroupMenuCell" forIndexPath:indexPath];
  395. cell.cell0ImgView.image = [UIImage imageNamed:model.image];
  396. cell.cell0TitleLabel.text = model.name;
  397. return cell;
  398. }
  399. /****************************************************/
  400. #pragma mark --UICollectionViewDelegateFlowLayout
  401. /****************************************************/
  402. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
  403. {
  404. CGFloat width = (SCREEN_WIDTH - 60 - 75) * 0.25;
  405. CGFloat height = Height_SCALE(100);
  406. return CGSizeMake(width, height);
  407. }
  408. //设置每个item的UIEdgeInsets
  409. - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
  410. {
  411. return UIEdgeInsetsMake(0, 0, 0, 0);
  412. }
  413. //设置每个item水平间距
  414. - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
  415. {
  416. return 25.f;
  417. }
  418. //设置每个item垂直间距
  419. - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
  420. {
  421. return 0.f;
  422. }
  423. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
  424. [collectionView deselectItemAtIndexPath:indexPath animated:YES];
  425. SmartBarModel * model = [self.listArray objectAtIndex:indexPath.item];
  426. if(self.delegate && [self.delegate respondsToSelector:@selector(chatBarClickMoreType:)]){
  427. [self.delegate chatBarClickMoreType:model.type];
  428. }
  429. }
  430. #pragma mark - CusView
  431. - (UICollectionView *)collectionView
  432. {
  433. if (!_collectionView) {
  434. _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:[[UICollectionViewFlowLayout alloc] init]];
  435. [_collectionView registerNib:[UINib nibWithNibName:@"NoticeNewGroupMenuCell" bundle:nil] forCellWithReuseIdentifier:@"NoticeNewGroupMenuCell"];
  436. _collectionView.backgroundColor = UIColorHex(#F4F4F6);
  437. _collectionView.showsVerticalScrollIndicator = NO;
  438. _collectionView.showsHorizontalScrollIndicator = NO;
  439. _collectionView.contentInset = UIEdgeInsetsMake(0, 30, 0, 30);
  440. _collectionView.alwaysBounceVertical = YES;
  441. _collectionView.scrollEnabled = NO;
  442. _collectionView.dataSource = self;
  443. _collectionView.delegate = self;
  444. }
  445. return _collectionView;
  446. }
  447. - (NSMutableArray *)listArray
  448. {
  449. if (!_listArray) {
  450. _listArray = [NSMutableArray array];
  451. }
  452. return _listArray;
  453. }
  454. @end