WFCUFaceBoard.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. //
  2. // FaceBoard.m
  3. //
  4. // Created by blue on 12-9-26.
  5. // Copyright (c) 2012年 blue. All rights reserved.
  6. // Email - 360511404@qq.com
  7. // http://github.com/bluemood
  8. #import "WFCUFaceBoard.h"
  9. #import "WFCUStickerItem.h"
  10. #import "YLImageView.h"
  11. #import "YLGIFImage.h"
  12. #import "WFCUFaceButton.h"
  13. #import "WFCUConfigManager.h"
  14. #define FACE_COUNT_ROW 4
  15. #define FACE_COUNT_CLU 7
  16. #define FACE_COUNT_PAGE ( FACE_COUNT_ROW * FACE_COUNT_CLU - 1)
  17. #define FACE_ICON_SIZE 44
  18. #define STICKER_COUNT_ROW 2
  19. #define STICKER_COUNT_CLU 4
  20. #define STICKER_COUNT_PAGE ( STICKER_COUNT_ROW * STICKER_COUNT_CLU)
  21. #define STICKER_ICON_SIZE 80
  22. @interface WFCUFaceBoard() <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate>
  23. @property(nonatomic, strong) NSArray *faceEmojiArray;
  24. @property(nonatomic,strong)UIView *tabbarView;
  25. @property(nonatomic,strong) UIButton *sendBtn;
  26. @property(nonatomic, strong)UIPageControl *facePageControl;
  27. @property(nonatomic, strong)UICollectionView *collectionView;
  28. @property(nonatomic, strong)UICollectionView *tabView;
  29. @property(nonatomic, strong)NSMutableDictionary<NSString *, WFCUStickerItem *> *stickers;
  30. @property(nonatomic, assign)int selectedTableRow;
  31. @end
  32. #define EMOJ_TAB_HEIGHT 42
  33. #define EMOJ_FACE_VIEW_HEIGHT 190
  34. #define EMOJ_PAGE_CONTROL_HEIGHT 20
  35. #define EMOJ_AREA_HEIGHT (EMOJ_TAB_HEIGHT + EMOJ_FACE_VIEW_HEIGHT + EMOJ_PAGE_CONTROL_HEIGHT)
  36. @implementation WFCUFaceBoard{
  37. int width;
  38. int location;
  39. }
  40. @synthesize delegate;
  41. + (NSString *)getStickerCachePath {
  42. NSArray * LibraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
  43. return [[LibraryPaths objectAtIndex:0] stringByAppendingFormat:@"/Caches/Patch/"];
  44. }
  45. + (NSString *)getStickerBundleName {
  46. NSString * bundleName = @"Stickers.bundle";
  47. return bundleName;
  48. }
  49. + (void)load {
  50. [WFCUFaceBoard initStickers];
  51. }
  52. + (void)initStickers {
  53. NSString * bundleName = [WFCUFaceBoard getStickerBundleName];
  54. NSError * err = nil;
  55. NSFileManager * defaultManager = [NSFileManager defaultManager];
  56. NSString * cacheBundleDir = [WFCUFaceBoard getStickerCachePath];
  57. NSLog(@"缓存资源目录: %@", cacheBundleDir);
  58. if (![defaultManager fileExistsAtPath:cacheBundleDir]) {
  59. [defaultManager createDirectoryAtPath:cacheBundleDir withIntermediateDirectories:YES attributes:nil error: &err];
  60. if(err){
  61. NSLog(@"初始化目录出错:%@", err);
  62. }
  63. NSString * defaultBundlePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent: bundleName];
  64. NSString * cacheBundlePath = [cacheBundleDir stringByAppendingPathComponent:bundleName];
  65. [defaultManager copyItemAtPath: defaultBundlePath toPath:cacheBundlePath error: &err];
  66. if(err){
  67. NSLog(@"复制初始资源文件出错:%@", err);
  68. }
  69. }
  70. }
  71. - (void)loadStickers {
  72. self.stickers = [[NSMutableDictionary alloc] init];
  73. NSString *stickerPath = [[WFCUFaceBoard getStickerCachePath] stringByAppendingPathComponent:[WFCUFaceBoard getStickerBundleName]];
  74. NSError * err = nil;
  75. NSFileManager * defaultManager = [NSFileManager defaultManager];
  76. NSArray *paths = [defaultManager contentsOfDirectoryAtPath:stickerPath error:&err];
  77. if (err != nil) {
  78. NSLog(@"error:%@", err);
  79. return;
  80. }
  81. for (NSString *file in paths) {
  82. BOOL isDir = false;
  83. NSString *absfile = [stickerPath stringByAppendingPathComponent:file];
  84. if ([defaultManager fileExistsAtPath:absfile isDirectory:&isDir]) {
  85. if (!isDir) {
  86. WFCUStickerItem *item = [[WFCUStickerItem alloc] init];
  87. item.key = file;
  88. item.tabIcon = absfile;
  89. item.stickerPaths = [[NSMutableArray alloc] init];
  90. NSString *name = [[file lastPathComponent] stringByDeletingPathExtension];
  91. NSString *stickerSubPath = [stickerPath stringByAppendingPathComponent:name];
  92. if ([defaultManager fileExistsAtPath:stickerSubPath isDirectory:&isDir]) {
  93. if (isDir) {
  94. NSArray *paths = [defaultManager contentsOfDirectoryAtPath:stickerSubPath error:&err];
  95. if (err != nil) {
  96. NSLog(@"error:%@", err);
  97. return;
  98. }
  99. for (NSString *p in paths) {
  100. NSString *stickerabsfile = [stickerSubPath stringByAppendingPathComponent:p];
  101. if ([defaultManager fileExistsAtPath:stickerabsfile isDirectory:&isDir]) {
  102. if (!isDir) {
  103. [item.stickerPaths addObject:stickerabsfile];
  104. }
  105. }
  106. }
  107. }
  108. }
  109. self.stickers[item.key] = item;
  110. } else {
  111. NSLog(@"is dir %@", absfile);
  112. }
  113. }
  114. }
  115. }
  116. - (id)init {
  117. width = [UIScreen mainScreen].bounds.size.width;
  118. self = [super initWithFrame:CGRectMake(0, 0, width, EMOJ_AREA_HEIGHT + kTabbarSafeBottomMargin)];
  119. [self loadStickers];
  120. if (self) {
  121. self.backgroundColor = [WFCUConfigManager globalManager].backgroudColor;
  122. NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
  123. NSString *bundlePath = [resourcePath stringByAppendingPathComponent:@"Emoj.plist"];
  124. self.faceEmojiArray = [[NSArray alloc]initWithContentsOfFile:bundlePath];
  125. [self addSubview:self.collectionView];
  126. //添加PageControl
  127. [self addSubview:self.facePageControl];
  128. _tabbarView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - EMOJ_TAB_HEIGHT - kTabbarSafeBottomMargin, self.frame.size.width, EMOJ_TAB_HEIGHT)];
  129. [self addSubview:_tabbarView];
  130. _sendBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  131. _sendBtn.tag = 333;
  132. _sendBtn.titleLabel.font = [UIFont systemFontOfSize:14.0f];
  133. _sendBtn.frame = CGRectMake(self.frame.size.width - 52,5,52, 37);
  134. [_sendBtn setTitle:@"发送" forState:UIControlStateNormal];
  135. [_sendBtn setTitleColor:[WFCUConfigManager globalManager].textColor forState:UIControlStateNormal];
  136. self.sendBtn.layer.borderWidth = 0.5f;
  137. self.sendBtn.layer.borderColor = HEXCOLOR(0xdbdbdd).CGColor;
  138. [_sendBtn addTarget:self action:@selector(sendBtnHandle:) forControlEvents:UIControlEventTouchUpInside];
  139. [_tabbarView addSubview:_sendBtn];
  140. [_tabbarView addSubview:self.tabView];
  141. [_collectionView reloadData];
  142. [self.tabView setAllowsMultipleSelection:NO];
  143. self.tabView.allowsSelection = YES;
  144. self.selectedTableRow = 0;
  145. }
  146. return self;
  147. }
  148. - (void)setSelectedTableRow:(int)selectedTableRow {
  149. _selectedTableRow = selectedTableRow;
  150. [self.tabView reloadData];
  151. }
  152. - (UICollectionView *)tabView {
  153. if (!_tabView) {
  154. UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
  155. layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  156. _tabView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,5,self.frame.size.width - 52, 37) collectionViewLayout:layout];
  157. _tabView.delegate = self;
  158. _tabView.dataSource = self;
  159. _tabView.backgroundColor = [WFCUConfigManager globalManager].backgroudColor;
  160. _tabView.showsHorizontalScrollIndicator = NO;
  161. _tabView.userInteractionEnabled = YES;
  162. [_tabView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellId"];
  163. }
  164. return _tabView;
  165. }
  166. - (UICollectionView *)collectionView {
  167. if (!_collectionView) {
  168. UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
  169. layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  170. layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 10);
  171. CGRect frame = self.bounds;
  172. frame.size.height = EMOJ_FACE_VIEW_HEIGHT;
  173. _collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
  174. _collectionView.delegate = self;
  175. _collectionView.dataSource = self;
  176. _collectionView.decelerationRate = 90;
  177. _collectionView.backgroundColor = [WFCUConfigManager globalManager].backgroudColor;
  178. _collectionView.showsHorizontalScrollIndicator = NO;
  179. [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellId"];
  180. }
  181. return _collectionView;
  182. }
  183. - (UIPageControl *)facePageControl {
  184. if (!_facePageControl) {
  185. _facePageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(width/2-50, EMOJ_FACE_VIEW_HEIGHT, 100, EMOJ_PAGE_CONTROL_HEIGHT)];
  186. [_facePageControl addTarget:self
  187. action:@selector(pageChange:)
  188. forControlEvents:UIControlEventValueChanged];
  189. _facePageControl.pageIndicatorTintColor = [UIColor grayColor];
  190. _facePageControl.currentPageIndicatorTintColor = [UIColor blackColor];
  191. _facePageControl.numberOfPages = [self getPagesCount:0];
  192. [self.tabView selectItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionNone];
  193. [self.tabView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]]];
  194. _facePageControl.currentPage = 0;
  195. }
  196. return _facePageControl;
  197. }
  198. - (void)sendBtnHandle:(id)sender {
  199. if ([self.delegate respondsToSelector:@selector(didTouchSendEmoj)]) {
  200. [self.delegate didTouchSendEmoj];
  201. }
  202. }
  203. - (int)pagesOfIndexPath:(NSIndexPath *)item {
  204. int pages = 0;
  205. for (int i = 0; i < item.section; i++) {
  206. pages += [self collectionView:self.collectionView numberOfItemsInSection:i];
  207. }
  208. pages += item.row;
  209. return pages;
  210. }
  211. - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
  212. if (scrollView == self.collectionView) {
  213. NSArray<NSIndexPath *> *items = [_collectionView indexPathsForVisibleItems];
  214. if (items.count == 2) {
  215. int pages0 = [self pagesOfIndexPath:items[0]];
  216. int pages1 = [self pagesOfIndexPath:items[1]];
  217. UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
  218. CGFloat offset0 = pages0 * (self.collectionView.bounds.size.width + layout.minimumLineSpacing);
  219. CGFloat offset1 = pages1 * (self.collectionView.bounds.size.width + layout.minimumInteritemSpacing);
  220. NSIndexPath *selectedOne;
  221. if (ABS(offset0-targetContentOffset->x) > ABS(offset1 - targetContentOffset->x)) {
  222. targetContentOffset->x = offset1;
  223. selectedOne = items[1];
  224. } else {
  225. targetContentOffset->x = offset0;
  226. selectedOne = items[0];
  227. }
  228. if (items[1].section != items[0].section) {
  229. self.facePageControl.numberOfPages = [self getPagesCount:selectedOne.section];
  230. self.selectedTableRow = selectedOne.section;
  231. }
  232. [self.facePageControl setCurrentPage:selectedOne.row];
  233. [self.facePageControl updateCurrentPageDisplay];
  234. } else if(items.count == 1) {
  235. int pages0 = [self pagesOfIndexPath:items[0]];
  236. UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
  237. CGFloat offset0 = pages0 * (self.collectionView.bounds.size.width + layout.minimumLineSpacing);
  238. targetContentOffset->x = offset0;
  239. }
  240. }
  241. }
  242. - (void)pageChange:(id)sender {
  243. }
  244. - (void)faceButton:(id)sender {
  245. int i = (int)((WFCUFaceButton*)sender).buttonIndex;
  246. if ([delegate respondsToSelector:@selector(didTouchEmoj:)]) {
  247. [delegate didTouchEmoj:self.faceEmojiArray[i]];
  248. }
  249. }
  250. - (void)backFace{
  251. if ([delegate respondsToSelector:@selector(didTouchBackEmoj)]) {
  252. [delegate didTouchBackEmoj];
  253. }
  254. }
  255. - (NSInteger)getPagesCount:(NSInteger)section {
  256. if (section == 0) {
  257. int FACE_COUNT_ALL = (int)self.faceEmojiArray.count;
  258. int pages;
  259. if (FACE_COUNT_ALL > 0) {
  260. pages = (FACE_COUNT_ALL - 1)/(FACE_COUNT_ROW * FACE_COUNT_CLU -1) + 1;
  261. } else {
  262. pages = 0;
  263. }
  264. return pages;
  265. } else {
  266. return (self.stickers[[self.stickers.allKeys objectAtIndex:(section - 1)]].stickerPaths.count - 1) / STICKER_COUNT_PAGE + 1;
  267. }
  268. }
  269. - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
  270. if (collectionView == self.collectionView) {
  271. if (self.disableSticker) {
  272. return 1;
  273. }
  274. return self.stickers.allKeys.count + 1;
  275. } else {
  276. return 1;
  277. }
  278. }
  279. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  280. if (collectionView == self.tabView) {
  281. NSIndexPath *minOne = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
  282. self.facePageControl.numberOfPages = [self getPagesCount:minOne.section];
  283. self.facePageControl.currentPage = 0;
  284. [_collectionView scrollToItemAtIndexPath:minOne atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
  285. self.selectedTableRow = indexPath.row;
  286. }
  287. }
  288. - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
  289. }
  290. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  291. if (collectionView == self.collectionView) {
  292. return [self getPagesCount:section];
  293. } else {
  294. if (self.disableSticker) {
  295. return 1;
  296. }
  297. return self.stickers.allKeys.count + 1;
  298. }
  299. }
  300. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
  301. if (collectionView == self.collectionView) {
  302. return self.collectionView.bounds.size;
  303. } else {
  304. return CGSizeMake(45, 37);
  305. }
  306. }
  307. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  308. UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellId" forIndexPath:indexPath];
  309. for (UIView *subView in [cell subviews]) {
  310. [subView removeFromSuperview];
  311. }
  312. if (collectionView == self.collectionView) {
  313. if (indexPath.section == 0) {
  314. int startPos = (int)indexPath.row * FACE_COUNT_PAGE;
  315. int endPos = (int)MIN(self.faceEmojiArray.count, startPos + FACE_COUNT_PAGE);
  316. for (int i = startPos; i <= endPos; i++) {
  317. int cli = (i - startPos)/FACE_COUNT_CLU;
  318. int col = (i - startPos)%FACE_COUNT_CLU;
  319. CGFloat x = col * width/7;
  320. CGFloat y = cli * FACE_ICON_SIZE + 8;
  321. if ((cli == FACE_COUNT_ROW -1 && col == FACE_COUNT_CLU - 1) || i == self.faceEmojiArray.count) {
  322. UIButton *back = [UIButton buttonWithType:UIButtonTypeCustom];
  323. [back setImage:[UIImage imageNamed:@"del_emoji_normal"] forState:UIControlStateNormal];
  324. [back setImage:[UIImage imageNamed:@"del_emoji_select"] forState:UIControlStateSelected];
  325. [back addTarget:self action:@selector(backFace) forControlEvents:UIControlEventTouchUpInside];
  326. if (i == self.faceEmojiArray.count) {
  327. x = (FACE_COUNT_CLU - 1) * width/7;
  328. y = (FACE_COUNT_ROW - 1) * FACE_ICON_SIZE + 8;
  329. }
  330. back.frame = CGRectMake( x, y, width/7, FACE_ICON_SIZE);
  331. [cell addSubview:back];
  332. } else {
  333. WFCUFaceButton *faceButton = [WFCUFaceButton buttonWithType:UIButtonTypeCustom];
  334. faceButton.buttonIndex = i;
  335. [faceButton addTarget:self
  336. action:@selector(faceButton:)
  337. forControlEvents:UIControlEventTouchUpInside];
  338. faceButton.frame = CGRectMake( x, y, width/7, FACE_ICON_SIZE);
  339. [faceButton setTitle:self.faceEmojiArray[i]
  340. forState:UIControlStateNormal];
  341. [cell addSubview:faceButton];
  342. }
  343. }
  344. } else {
  345. NSArray *paths = self.stickers[self.stickers.allKeys[indexPath.section - 1]].stickerPaths;
  346. int startPos = (int)indexPath.row * STICKER_COUNT_PAGE;
  347. int endPos = (int)MIN(paths.count, startPos + STICKER_COUNT_PAGE);
  348. for (int i = startPos; i < endPos; i++) {
  349. int cli = (i - startPos)/STICKER_COUNT_CLU;
  350. int col = (i - startPos)%STICKER_COUNT_CLU;
  351. CGFloat x = col * width/STICKER_COUNT_CLU;
  352. CGFloat y = cli * STICKER_ICON_SIZE + 8;
  353. UIImageView *imageView;
  354. if ([[paths[i] pathExtension] isEqualToString:@"gif"]) {
  355. imageView = [[YLImageView alloc] initWithFrame:CGRectMake( x + 10, y, width/STICKER_COUNT_CLU - 20, STICKER_ICON_SIZE)];
  356. imageView.image = [YLGIFImage imageWithContentsOfFile:paths[i]];
  357. } else {
  358. imageView = [[UIImageView alloc] initWithFrame:CGRectMake( x + 10, y, width/STICKER_COUNT_CLU - 20, STICKER_ICON_SIZE)];
  359. imageView.image = [UIImage imageWithContentsOfFile:paths[i]];
  360. }
  361. [imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapSticker:)]];
  362. imageView.userInteractionEnabled = YES;
  363. long tag = indexPath.section;
  364. tag <<= 16;
  365. tag += i;
  366. imageView.tag = tag;
  367. [cell addSubview:imageView];
  368. }
  369. }
  370. } else {
  371. UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(11, 7, 23, 23)];
  372. if (indexPath.row == self.selectedTableRow) {
  373. cell.backgroundColor = HEXCOLOR(0xa8a8a8);;
  374. } else {
  375. cell.backgroundColor = [WFCUConfigManager globalManager].backgroudColor;
  376. }
  377. if (indexPath.row == 0) {
  378. iv.image = [UIImage imageNamed:@"emoji_btn_normal"];
  379. } else {
  380. iv.image = [UIImage imageWithContentsOfFile:self.stickers[self.stickers.allKeys[indexPath.row - 1]].tabIcon];
  381. }
  382. [cell addSubview:iv];
  383. }
  384. return cell;
  385. }
  386. - (void)onTapSticker:(UITapGestureRecognizer *)sender {
  387. UIView *view = sender.view;
  388. long tag = view.tag;
  389. long i = tag & 0xFFFF;
  390. long section = tag >> 16;
  391. NSString *selectSticker = self.stickers[self.stickers.allKeys[section - 1]].stickerPaths[i];
  392. if ([self.delegate respondsToSelector:@selector(didSelectedSticker:)]) {
  393. [self.delegate didSelectedSticker:selectSticker];
  394. }
  395. }
  396. @end