单军华
2018-07-11 acdf41fa3b32b628d9d7bba1f975060567dad3d7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//
//  HMEmoticonInputView.m
//  表情键盘
//
//  Created by 刘凡 on 16/3/3.
//  Copyright © 2016年 itcast. All rights reserved.
//
 
#import "HMEmoticonInputView.h"
#import "HMEmoticonToolbar.h"
#import "UIImage+HMEmoticon.h"
#import "HMEmoticonManager.h"
#import "HMEmoticonCell.h"
 
/// 表情 Cell 可重用标识符号
NSString *const HMEmoticonCellIdentifier = @"HMEmoticonCellIdentifier";
 
#pragma mark - 表情键盘布局
@interface HMEmoticonKeyboardLayout : UICollectionViewFlowLayout
 
@end
 
@implementation HMEmoticonKeyboardLayout
 
- (void)prepareLayout {
    [super prepareLayout];
    
    self.itemSize = self.collectionView.bounds.size;
    self.minimumInteritemSpacing = 0;
    self.minimumLineSpacing = 0;
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    
    self.collectionView.pagingEnabled = YES;
    self.collectionView.showsHorizontalScrollIndicator = NO;
    self.collectionView.bounces = NO;
}
 
@end
 
#pragma mark - 表情输入视图
@interface HMEmoticonInputView() <UICollectionViewDataSource, UICollectionViewDelegate, HMEmoticonToolbarDelegate, HMEmoticonCellDelegate>
 
@end
 
@implementation HMEmoticonInputView {
    UICollectionView *_collectionView;
    HMEmoticonToolbar *_toolbar;
    UIPageControl *_pageControl;
    
    void (^_selectedEmoticonCallBack)(HMEmoticon * _Nullable, BOOL);
}
 
#pragma mark - 构造函数
- (instancetype)initWithSelectedEmoticon:(void (^)(HMEmoticon * _Nullable, BOOL))selectedEmoticon {
    CGRect frame = [UIScreen mainScreen].bounds;
    frame.size.height = 216;
    
    self = [super initWithFrame:frame];
    if (self) {
        _selectedEmoticonCallBack = selectedEmoticon;
        
        [self prepareUI];
        
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:1];
        [_collectionView scrollToItemAtIndexPath:indexPath
                                atScrollPosition:UICollectionViewScrollPositionLeft
                                        animated:NO];
        [self updatePageControlWithIndexPath:indexPath];
        [_toolbar selectSection:indexPath.section];
    }
    return self;
}
 
- (instancetype)initWithFrame:(CGRect)frame {
    NSAssert(NO, @"请调用 initWithSelectedEmoticon: 实例化表情输入视图");
    return nil;
}
 
#pragma mark - HMEmoticonToolbarDelegate
- (void)emoticonToolbarDidSelectSection:(NSInteger)section {
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section];
    
    [_collectionView scrollToItemAtIndexPath:indexPath
                            atScrollPosition:UICollectionViewScrollPositionLeft
                                    animated:NO];
    [self updatePageControlWithIndexPath:indexPath];
}
 
#pragma mark - HMEmoticonCellDelegate
- (void)emoticonCellDidSelectedEmoticon:(HMEmoticon *)emoticon isRemoved:(BOOL)isRemoved {
    if (_selectedEmoticonCallBack != nil) {
        _selectedEmoticonCallBack(emoticon, isRemoved);
    }
    
    /// 添加最近使用表情
    if (emoticon != nil) {
        [[HMEmoticonManager sharedManager] addRecentEmoticon:emoticon];
        
        // 如果当前停留不是在默认表情页,就更新默认表情页数据
        if ([_collectionView indexPathsForVisibleItems].firstObject.section != 0) {
            [_collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
        }
    }
}
 
#pragma mark - UICollectionViewDataSource, UICollectionViewDelegate
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return [HMEmoticonManager sharedManager].packages.count;
}
 
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [[HMEmoticonManager sharedManager] numberOfPagesInSection:section];
}
 
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    HMEmoticonCell *cell = [collectionView
                            dequeueReusableCellWithReuseIdentifier:HMEmoticonCellIdentifier
                            forIndexPath:indexPath];
    
    cell.emoticons = [[HMEmoticonManager sharedManager] emoticonsWithIndexPath:indexPath];
    cell.indexPath = indexPath;
    cell.delegate = self;
    
    return cell;
}
 
#pragma mark - UIScrollView Delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGPoint center = scrollView.center;
    center.x += scrollView.contentOffset.x;
    
    NSArray *indexPaths = [_collectionView indexPathsForVisibleItems];
    
    NSIndexPath *targetPath = nil;
    for (NSIndexPath *indexPath in indexPaths) {
        UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath];
        
        if (CGRectContainsPoint(cell.frame, center)) {
            targetPath = indexPath;
            break;
        }
    }
    
    if (targetPath != nil) {
        [self updatePageControlWithIndexPath:targetPath];
        [_toolbar selectSection:targetPath.section];
    }
}
 
- (void)updatePageControlWithIndexPath:(NSIndexPath *)indexPath {
    _pageControl.numberOfPages = [[HMEmoticonManager sharedManager] numberOfPagesInSection:indexPath.section];
    _pageControl.currentPage = indexPath.item;
}
 
#pragma mark - 设置界面
- (void)prepareUI {
    // 1. 基本属性设置
    self.backgroundColor = [UIColor colorWithPatternImage:[UIImage hm_imageNamed:@"emoticon_keyboard_background"]];
    
    // 2. 添加工具栏
    _toolbar = [[HMEmoticonToolbar alloc] init];
    [self addSubview:_toolbar];
    
    // 设置工具栏位置
    CGFloat toolbarHeight = 42;
    CGRect toolbarRect = self.bounds;
    toolbarRect.origin.y = toolbarRect.size.height - toolbarHeight;
    toolbarRect.size.height = toolbarHeight;
    _toolbar.frame = toolbarRect;
    
    _toolbar.delegate = self;
    
    // 3. 添加 collectionView
    CGRect collectionViewRect = self.bounds;
    collectionViewRect.size.height -= toolbarHeight;
    _collectionView = [[UICollectionView alloc]
                       initWithFrame:collectionViewRect
                       collectionViewLayout:[[HMEmoticonKeyboardLayout alloc] init]];
    [self addSubview:_collectionView];
    
    // 设置 collectionView
    _collectionView.backgroundColor = [UIColor clearColor];
    
    _collectionView.dataSource = self;
    _collectionView.delegate = self;
    
    [_collectionView registerClass:[HMEmoticonCell class] forCellWithReuseIdentifier:HMEmoticonCellIdentifier];
    
    // 4. 分页控件
    _pageControl = [[UIPageControl alloc] init];
    [self addSubview:_pageControl];
    
    // 设置分页控件
    _pageControl.hidesForSinglePage = YES;
    _pageControl.userInteractionEnabled = NO;
    
    [_pageControl setValue:[UIImage hm_imageNamed:@"compose_keyboard_dot_selected"] forKey:@"_currentPageImage"];
    [_pageControl setValue:[UIImage hm_imageNamed:@"compose_keyboard_dot_normal"] forKey:@"_pageImage"];
    
    // 自动布局
    _pageControl.translatesAutoresizingMaskIntoConstraints = NO;
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_pageControl
                                                     attribute:NSLayoutAttributeCenterX
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:self
                                                     attribute:NSLayoutAttributeCenterX
                                                    multiplier:1.0
                                                      constant:0.0]];
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_pageControl
                                                     attribute:NSLayoutAttributeBottom
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:_toolbar
                                                     attribute:NSLayoutAttributeTop
                                                    multiplier:1.0
                                                      constant:0.0]];
}
 
@end