本節主要内容:
1.自定義鍵盤--将工具欄添加到鍵盤上,并實作切換
2.實作進入到系統相冊選取圖檔
3.實作表情布局
4.實作系統鍵盤和表情視圖之間的切換
5.表情消息的追加
一、*自定義鍵盤
建立子視圖,為系統鍵盤添加工具欄。例子中建立了textView和一個帶有5個button的編輯工具欄
#pragma mark - 建立子視圖
- (void)creactSubView{
//1 添加_textView
_textView = [[UITextView alloc] initWithFrame:CGRectMake(, , kScreenWidth, kScreenHeight-)];
_textView.backgroundColor = [UIColor clearColor];
_textView.font = [UIFont systemFontOfSize:];
[_textView becomeFirstResponder];
[self.view addSubview:_textView];
//2 編輯欄
_editorView = [[UIView alloc] initWithFrame:CGRectMake(, _textView.bottom, kScreenWidth, )];
_editorView.backgroundColor = [UIColor clearColor];
//***将_editorView添加到系統鍵盤上,利用下面的inputAccessoryView方法
_textView.inputAccessoryView = _editorView;
//添加5個按鈕
NSArray *imgArr = @[
@"compose_toolbar_1.png",
@"compose_toolbar_3.png",
@"compose_toolbar_4.png",
@"compose_toolbar_5.png",
@"compose_toolbar_6.png"
];
CGFloat btnWidth = kScreenWidth/;
for (int i = ; i<imgArr.count; i++) {
ThemeButton *button = [[ThemeButton alloc] initWithFrame:CGRectMake(btnWidth*i, , btnWidth, )];
button.imageName = imgArr[i];
[button addTarget:self action:@selector(pressAction:) forControlEvents:UIControlEventTouchUpInside];
button.tag = +i;
[_editorView addSubview:button];
}
}
二、*進入系統相冊選取圖檔
按鈕1的響應事件—實作進入系統相冊選取圖檔(單張)
switch (button.tag - ) {
case :
NSLog(@"點選第一個按鈕");
{
//由底部彈出的彈窗
UIAlertController *alter = [UIAlertController alertControllerWithTitle:@"選取圖檔" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"相冊" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//選取相冊
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
picker.delegate = self;
//模态視圖 彈出相冊
[self presentViewController:picker animated:YES completion:nil];
}];
[alter addAction:action];
[self presentViewController:alter animated:YES completion:nil];
}
break;
三、*表情布局
要實作的效果:
所有表情分成幾頁,每頁按照4行7列進行排列,點選任意表情會出現該表情的放大鏡,放大鏡上有該表情和文字。能夠實作頁面的滑動。
思路:
1.資料處理
從plist檔案中取出所有檔案,将其存放進一個大的數組中,将這個大數組分割成28個資料一組的小數組,小數組的數量将會對應頁面的數量。而在每個小數組裡面,這28個資料将會按照4行7列進行排列。
2.頁面處理
由外至内視圖分别是:UIView->UIScrolleView->UIView->UIImageView(表情視圖和選中視圖)
代碼:
FaceView
.h檔案
#import <UIKit/UIKit.h>
#import "UIViewExt.h"
@interface FaceView : UIView
@property (nonatomic, strong) NSMutableArray *items;//表情大數組
@property (nonatomic, strong) UIImageView *selectImgView;//選中的放大鏡視圖
@property (nonatomic, assign) NSString *selectImgName;//選中的表情名字
@property (nonatomic, strong) UILabel *label;
@end
.m檔案
#import "FaceView.h"
#import "Header.h"
#define imgSize 30
@implementation FaceView
- (instancetype) initWithFrame:(CGRect)frame {
if ([super initWithFrame:frame]) {
[self loadPlist];
_label = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
_label.font = [UIFont systemFontOfSize:];
}
return self;
}
//整理表情
- (void) loadPlist {
//擷取plist檔案
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"emoticons.plist" ofType:nil];
//所有表情數組
NSArray *array = [NSArray arrayWithContentsOfFile:filePath];
//大數組
_items = [NSMutableArray array];
//小數組
NSMutableArray *items2D = nil;
for (int i = ; i < array.count; i++) {
//建立小數組
if (items2D == nil || items2D.count == ) {
items2D = [NSMutableArray array];
[_items addObject:items2D];
}
NSDictionary *faceDic = [array objectAtIndex:i];
[items2D addObject:faceDic];
}
//内部寫死寬高
self.width = kScreenWidth * _items.count;
self.height = * itemSize;
}
//繪制
- (void)drawRect:(CGRect)rect {
//确定行和列
CGFloat row = ;
CGFloat culom = ;
//拿表情
for (int i = ; i < _items.count; i++) {
NSMutableArray *item2D = _items[i];
for (int j = ; j < item2D.count; j++) {
NSDictionary *dic = item2D[j];
//圖檔名字
NSString *imageName = [dic objectForKey:@"png"];
UIImage *img = [UIImage imageNamed:imageName];
CGFloat x = culom * itemSize + (itemSize-imgSize)/ + kScreenWidth * i;
CGFloat y = row * itemSize + (itemSize - imgSize)/;
//繪制
[img drawInRect:CGRectMake(x, y, imgSize, imgSize)];
//更新行和列
culom++;
if (culom == ) {
culom = ;
row++;
}
if (row == ) {
row = ;
}
}
}
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//放大鏡不隐藏
_selectImgView.hidden = NO;
//禁止滑動
if ([self.superview isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollV = (UIScrollView *) self.superview;
scrollV.scrollEnabled = NO;
}
//拿到觸摸的坐标
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
[self touchFace:point];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
[self touchFace:point];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//隐藏放大鏡
_selectImgView.hidden = YES;
//開啟滑動
if ([self.superview isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollV = (UIScrollView *)self.superview;
scrollV.scrollEnabled = YES;
}
//回調block
}
//尋找點選的表情
- (void) touchFace:(CGPoint) point {
//1.目前頁
NSInteger page = point.x/kScreenWidth;
//容錯處理
if (page>=_items.count || page < ) {
return;
}
//确定小數組的索引
/**根據這個計算
CGFloat x = culom *itemSize + (itemSize-imgSize)/2 + kScreenWidth*i;
CGFloat y = row *itemSize +(itemSize-imgSize)/2;
*/
NSInteger culom = (point.x - ((itemSize-imgSize)/ + kScreenWidth*page))/itemSize;//列
NSInteger row = (point.y - (itemSize-imgSize)/)/itemSize;//行
//容錯處理
if (culom >) culom =;
if (culom <) culom =;
if (row >) row =;
if (row <) row =;
//根據目前頁面坐标計算行和咧
NSInteger index = row*+culom;
//處理最後一頁數組越界
if (page == _items.count-) {
//通過頁面擷取小數組
NSArray *item2D = _items[page];
if (index>item2D.count-) {
return;
}
}
NSArray *item2D = _items[page];
NSDictionary *faceDic = item2D[index];
//表情圖檔名
NSString *imgName = faceDic[@"png"];
//表情中文名
NSString *faceName = faceDic[@"chs"];
if (![self.selectImgName isEqualToString:faceName]) {
//确定放大鏡的位置
CGFloat bottom = row *itemSize +itemSize/;
CGFloat x = culom *itemSize + itemSize/ + page *kScreenWidth;
self.selectImgView.center = CGPointMake(x, );
self.selectImgView.bottom = bottom;
//指派-選中的表情圖檔顯示
UIImageView *imgView =[self.selectImgView viewWithTag:];
imgView.image = [UIImage imageNamed:imgName];
self.selectImgName = faceName;
[_selectImgView addSubview:_label];
//選中的表情名
_label.text = _selectImgName;
}
//發送通知--參數:選中的圖檔名faceName
NSDictionary *userInfo = @{@"imageName" : faceName};
[[NSNotificationCenter defaultCenter] postNotificationName:@"imageNameNo"
object:nil
userInfo:userInfo];
}
//選中視圖
- (UIImageView *) selectImgView {
if (_selectImgView == nil) {
//建立選中視圖
_selectImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"emoticon_keyboard_magnifier.png"]];
[_selectImgView sizeToFit];
[self addSubview:_selectImgView];
//選中視圖中的表情
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake((_selectImgView.width-imgSize)/, , imgSize, imgSize)];
imgView.tag = ;
[_selectImgView addSubview:imgView];
}
return _selectImgView;
}
@end
FaceFnel
.h檔案
#import <UIKit/UIKit.h>
#import "FaceView.h"
@interface FaceFnel : UIView <UIScrollViewDelegate>
@end
.m檔案
#import "FaceFnel.h"
#import "Header.h"
@implementation FaceFnel
/**
faceView---表情視圖
scroll----滑動視圖
page---分頁控件
*/
- (instancetype) initWithFrame:(CGRect)frame {
if ([super initWithFrame:frame]) {
[self createSubView];
}
return self;
}
- (void) createSubView {
//建立faceView
FaceView *faceView = [[FaceView alloc] initWithFrame:CGRectMake(, , , )];
faceView.backgroundColor = [UIColor clearColor];
//建立scrollView
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(, , kScreenWidth, faceView.height)];
scrollView.contentSize = CGSizeMake(faceView.width, faceView.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
//裁剪
scrollView.clipsToBounds = NO;
scrollView.pagingEnabled = YES;
scrollView.delegate = self;
[scrollView addSubview:faceView];
[self addSubview:scrollView];
//建立分頁控件
UIPageControl *pageC = [[UIPageControl alloc] initWithFrame:CGRectMake(, faceView.bottom, kScreenWidth, )];
pageC.numberOfPages = faceView.items.count;
pageC.tag = ;
//目前視圖的寬高計算
self.width = kScreenWidth;
self.height = faceView.height + pageC.height;
[self addSubview:pageC];
}
#pragma mark -滑動視圖代理方法
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
//計算index--index代表圓點的下标
NSInteger index = scrollView.contentOffset.x/kScreenWidth;
UIPageControl *pageC = (UIPageControl *) [self viewWithTag:];
pageC.currentPage = index;
}
- (void) drawRect:(CGRect)rect {
UIImage *img = [UIImage imageNamed:@"emoticon_keyboard_background.png"];
[img drawInRect:rect];
}
@end
#pragma mark - 圖檔的代理方法
- (void)imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(nonnull NSDictionary<NSString *,id> *)info {
[picker dismissViewControllerAnimated:YES completion:nil];
[_textView becomeFirstResponder];
UIImage *img = info[@"UIImagePickerControllerOriginalImage"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(, -, , )];
imageView.image = img;
_sendImg = img;
[_editorView addSubview:imageView];
}
四、系統鍵盤與表情視圖之間互相切換
case :
{
// [self loadImage];
//按鈕取反
button.selected = !button.selected;
if (button.selected == YES) {
//收起鍵盤
[_textView resignFirstResponder];
//顯示表情視圖
_textView.inputView = _faceview;
//彈出鍵盤
[_textView becomeFirstResponder];
} else {
[_textView resignFirstResponder];
//顯示系統鍵盤
_textView.inputView = nil;
[_textView becomeFirstResponder];
}
}
break;
五、消息追加
這裡的思路是将圖檔的中文名作為參數,利用通知傳過來,将其複制給_textView.text上。
//發送通知
NSDictionary *userInfo = @{@"imageName" : faceName};
[[NSNotificationCenter defaultCenter] postNotificationName:@"imageNameNo" object:nil userInfo:userInfo];
//接收通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ImgaeNameChange:) name:@"imageNameNo" object:nil];
#pragma mark - 通知的實作
- (void) ImgaeNameChange:(NSNotification *) noti {
NSString *text = [noti.userInfo objectForKey:@"imageName"];
//追加
_textView.text = [_textView.text stringByAppendingString:text];
}
//移除通知
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageNameNo" object:nil];
}