下面的東西是編寫自定義的表情鍵盤,話很少說,開門見山吧!下面主要用到的知識有MVC, iOS開發中的自動佈局,自定義組件的封裝與使用,Block回調,CoreData的使用。有的小夥伴可能會問寫一個自定義表情鍵盤腫麼這麼麻煩?下面將會介紹咱們如何用上面提到的東西來定義咱們的表情鍵盤。下面的內容會比較多,這篇博文仍是比較有料的。html
仍是那句話寫技術博客是少不了代碼的,下面會結合代碼來回顧一下iOS的知識,本篇博文中用到的知識點在前面的博客中都能找到相應的內容,本篇算是一個小小的功能整合。先來張圖看一下本app的目錄結構。我是根據本身對MVC的理解來構建的目錄結構,但願起到拋磚引玉的做用,有好的解決方案歡迎評論或者留言指出。Face文件中存放的時咱們的表情圖片,Model文件封裝的是從sqlite中讀取歷史頭像的組件,View文件中封裝的時咱們自定義的組件,也就是自定義鍵盤相關的視圖,Controller負責將咱們的各個組件組裝到一塊兒完成咱們想要的功能。下面會一一介紹。java
上面是文件的組織結構,下面爲了更爲直觀的瞭解咱們想要的效果,下面先看幾張截圖,來直觀的感覺一下運行效果,上面是豎屏的顯示效果,下面是橫屏的顯示效果。由於在封裝自定義鍵盤中用到了自動佈局因此橫屏顯示或者在更大的屏幕上顯示是沒問題的,經常使用表情是用戶用過的表情,而後存在Sqlite中,顯示時並按時間降序排列。more是用來擴展功能用的接口。話很少說,來的代碼纔是實在的。git
一.View(自定義視圖)github
View文件夾下存放的時咱們自定義的視圖組件,由於是自定義的組件因此storyboard咱們就用不了啦,全部的代碼都必須手寫,這樣才能保證組件使用的靈活性和減小各個組件之間的耦合性,更利於團隊之間的合做。在封裝組件時要預留好外界可能使用到的接口,和返回該返回的數據。好啦,廢話少說,來點乾貨吧!sql
一、FaceView組件的封裝:FaceView即負責顯示一個個的頭像。在使用該組件時要傳入要顯示的圖片和圖片對應的文字(如【哈哈】),當點擊圖片的時候,會經過block回調的形式把該圖片的image以及圖片文字返回到使用的組件中去,下面是關鍵代碼:數據庫
FaceView.h中的代碼以下(下面代碼是定義啦相應的Block類型和對外的接口):app
1 #import <UIKit/UIKit.h> 2 3 //聲明表情對應的block,用於把點擊的表情的圖片和圖片信息傳到上層視圖 4 typedef void (^FaceBlock) (UIImage *image, NSString *imageText); 5 6 @interface FaceView : UIView 7 8 //圖片對應的文字 9 @property (nonatomic, strong) NSString *imageText; 10 //表情圖片 11 @property (nonatomic, strong) UIImage *headerImage; 12 13 //設置block回調 14 -(void)setFaceBlock:(FaceBlock)block; 15 16 //設置圖片,文字 17 -(void)setImage:(UIImage *) image ImageText:(NSString *) text; 18 19 @end
FaceView.m中的代碼以下ide
1 // 2 // FaceView.m 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 #import "FaceView.h" 10 11 @interface FaceView () 12 @property(strong, nonatomic) FaceBlock block; 13 @property (strong, nonatomic) UIImageView *imageView; 14 @end 15 16 @implementation FaceView 17 18 //初始化圖片 19 - (id)initWithFrame:(CGRect)frame 20 { 21 //face的大小 22 frame.size.height = 30; 23 frame.size.width = 30; 24 self = [super initWithFrame:frame]; 25 if (self) { 26 self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; 27 [self addSubview:self.imageView]; 28 } 29 return self; 30 } 31 32 -(void) setFaceBlock:(FaceBlock)block 33 { 34 self.block = block; 35 } 36 37 38 -(void) setImage:(UIImage *)image ImageText:(NSString *)text 39 { 40 //顯示圖片 41 [self.imageView setImage:image]; 42 43 //把圖片存儲起來 44 self.headerImage = image; 45 46 self.imageText = text; 47 } 48 49 //點擊時回調 50 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 51 { 52 UITouch *touch = [touches anyObject]; 53 CGPoint point = [touch locationInView:self]; 54 //判斷觸摸的結束點是否在圖片中 55 if (CGRectContainsPoint(self.bounds, point)) 56 { 57 //回調,把該頭像的信息傳到相應的controller中 58 self.block(self.headerImage, self.imageText); 59 } 60 } 61 62 @end
代碼說明:函數
主要就是block回調的使用,就是封裝了一個自定義的button,具體內容請參考以前的博客「IOS開發之自定義Button(集成三種回調模式)」工具
二、FunctionView組件的封裝,FunctionView就是使用FaceView組件和ScrollView組件把表情加載進來,在實例化FunctionView組件時,咱們用到了自動佈局來設置ScrollView和下面的Button
FunctionView.h的代碼以下,在.h中留有組件的接口和回調用的Block, plistFileName用於加載咱們的資源文件時使用,至於如何使用plist文件,請參考以前的博客:IOS開發之顯示微博表情
1 // 2 // FunctionView.h 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 //定義對應的block類型,用於數據的交互 12 typedef void (^FunctionBlock) (UIImage *image, NSString *imageText); 13 14 @interface FunctionView : UIView 15 //資源文件名 16 @property (nonatomic, strong) NSString *plistFileName; 17 //接受block塊 18 -(void)setFunctionBlock:(FunctionBlock) block; 19 20 @end
FunctionView.m中的代碼以下,經常使用表情是在sqlite中獲取的,而所有表情是經過plist文件的信息在Face文件中加載的:
1 // 2 // FunctionView.m 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 #import "FunctionView.h" 10 #import "FaceView.h" 11 #import "ImageModelClass.h" 12 #import "HistoryImage.h" 13 14 @interface FunctionView() 15 16 @property (strong, nonatomic) FunctionBlock block; 17 //暫存表情組件回調的表情和表情文字 18 @property (strong, nonatomic) UIImage *headerImage; 19 @property (strong, nonatomic) NSString *imageText; 20 21 //display咱們的表情圖片 22 @property (strong, nonatomic) UIScrollView *headerScrollView; 23 24 //定義數據模型用於獲取歷史表情 25 @property (strong, nonatomic) ImageModelClass *imageModel; 26 27 @end 28 29 30 @implementation FunctionView 31 - (id)initWithFrame:(CGRect)frame 32 { 33 self = [super initWithFrame:frame]; 34 if (self) { 35 36 //實例化數據模型 37 self.imageModel =[[ImageModelClass alloc] init]; 38 39 //實例化下面的button 40 UIButton *faceButton = [[UIButton alloc] initWithFrame:CGRectZero]; 41 faceButton.backgroundColor = [UIColor grayColor]; 42 43 [faceButton setTitle:@"所有表情" forState:UIControlStateNormal]; 44 [faceButton setShowsTouchWhenHighlighted:YES]; 45 [faceButton addTarget:self action:@selector(tapButton1:) forControlEvents:UIControlEventTouchUpInside]; 46 [self addSubview:faceButton]; 47 48 49 //實例化經常使用表情按鈕 50 UIButton *moreButton = [[UIButton alloc] initWithFrame:CGRectZero]; 51 moreButton.backgroundColor = [UIColor orangeColor]; 52 [moreButton setTitle:@"經常使用表情" forState:UIControlStateNormal]; 53 [moreButton setShowsTouchWhenHighlighted:YES]; 54 [moreButton addTarget:self action:@selector(tapButton2:) forControlEvents:UIControlEventTouchUpInside]; 55 [self addSubview:moreButton]; 56 57 //給按鈕添加約束 58 faceButton.translatesAutoresizingMaskIntoConstraints = NO; 59 moreButton.translatesAutoresizingMaskIntoConstraints = NO; 60 //水平約束 61 NSArray *buttonH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[faceButton][moreButton(==faceButton)]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(faceButton,moreButton)]; 62 [self addConstraints:buttonH]; 63 64 //垂直約束 65 NSArray *button1V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[faceButton(44)]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(faceButton)]; 66 [self addConstraints:button1V]; 67 68 NSArray *button2V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[moreButton(44)]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(moreButton)]; 69 [self addConstraints:button2V]; 70 71 //默認顯示錶情圖片 72 [self tapButton1:nil]; 73 74 } 75 return self; 76 } 77 78 //接受回調 79 -(void)setFunctionBlock:(FunctionBlock)block 80 { 81 self.block = block; 82 } 83 84 //點擊所有表情按鈕回調方法 85 -(void)tapButton1: (id) sender 86 { 87 // 從plist文件載入資源 88 NSBundle *bundle = [NSBundle mainBundle]; 89 NSString *path = [bundle pathForResource:self.plistFileName ofType:@"plist"]; 90 NSArray *headers = [NSArray arrayWithContentsOfFile:path]; 91 92 if (headers.count == 0) { 93 NSLog(@"訪問的plist文件不存在"); 94 } 95 else 96 { 97 //調用headers方法顯示錶情 98 [self header:headers]; 99 } 100 } 101 102 //點擊歷史表情的回調方法 103 -(void) tapButton2: (id) sender 104 { 105 //從數據庫中查詢全部的圖片 106 NSArray *imageData = [self.imageModel queryAll]; 107 //解析請求到的數據 108 NSMutableArray *headers = [NSMutableArray arrayWithCapacity:imageData.count]; 109 110 //數據實體,至關於javaBean的東西 111 HistoryImage *tempData; 112 113 for (int i = 0; i < imageData.count; i ++) { 114 tempData = imageData[i]; 115 116 //解析數據,轉換成函數headers要用的數據格式 117 NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:2]; 118 [dic setObject:tempData.imageText forKey:@"chs"]; 119 UIImage *image = [UIImage imageWithData:tempData.headerImage]; 120 [dic setObject:image forKey:@"png"]; 121 122 [headers addObject:dic]; 123 } 124 125 [self header:headers]; 126 127 } 128 129 130 //負責把查出來的圖片顯示 131 -(void) header:(NSArray *)headers 132 { 133 [self.headerScrollView removeFromSuperview]; 134 self.headerScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero]; 135 [self addSubview:self.headerScrollView]; 136 137 //給scrollView添加約束 138 self.headerScrollView.translatesAutoresizingMaskIntoConstraints = NO; 139 //水平約束 140 NSArray *scrollH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[_headerScrollView]-10-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(_headerScrollView)]; 141 [self addConstraints:scrollH]; 142 143 //垂直約束 144 NSArray *scrolV = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_headerScrollView]-50-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(_headerScrollView)]; 145 [self addConstraints:scrolV]; 146 147 148 149 CGFloat scrollHeight = (self.frame).size.height-60; 150 151 //根據圖片量來計算scrollView的Contain的寬度 152 CGFloat width = (headers.count/(scrollHeight/30))*30; 153 self.headerScrollView.contentSize = CGSizeMake(width, scrollHeight); 154 self.headerScrollView.pagingEnabled = YES; 155 156 157 //圖片座標 158 CGFloat x = 0; 159 CGFloat y = 0; 160 161 //往scroll上貼圖片 162 for (int i = 0; i < headers.count; i ++) { 163 //獲取圖片信息 164 UIImage *image; 165 if ([headers[i][@"png"] isKindOfClass:[NSString class]]) 166 { 167 image = [UIImage imageNamed:headers[i][@"png"]]; 168 } 169 else 170 { 171 image = headers[i][@"png"]; 172 } 173 174 NSString *imageText = headers[i][@"chs"]; 175 176 //計算圖片位置 177 y = (i%(int)(scrollHeight/30)) * 30; 178 x = (i/(int)(scrollHeight/30)) * 30; 179 180 FaceView *face = [[FaceView alloc] initWithFrame:CGRectMake(x, y, 0, 0)]; 181 [face setImage:image ImageText:imageText]; 182 183 //face的回調,當face點擊時獲取face的圖片 184 __weak __block FunctionView *copy_self = self; 185 [face setFaceBlock:^(UIImage *image, NSString *imageText) 186 { 187 copy_self.block(image, imageText); 188 }]; 189 190 [self.headerScrollView addSubview:face]; 191 } 192 193 [self.headerScrollView setNeedsDisplay]; 194 195 } 196 197 @end
代碼說明:
一、主要是經過對資源文件或者對從數據庫中查詢的資源進行遍歷而後添加到ScrollView中
2.爲了適應不一樣的屏幕給相應的組件添加了約束
3.ToolView組件的封裝: ToolView就是在主屏幕上下面的相似於TabBar的東西,當鍵盤出來的時候,ToolView會運動到鍵盤上面的位置。爲了使用不一樣的屏幕,也須要用自動佈局來實現。
ToolView.h的代碼以下:預留組件接口和聲明block類型
1 // 2 // ToolView.h 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 /***************** 10 封裝下面的工具條組件 11 *****************/ 12 #import <UIKit/UIKit.h> 13 14 //定義block塊變量類型,用於回調,把本View上的按鈕的index傳到Controller中 15 typedef void (^ToolIndex) (NSInteger index); 16 17 @interface ToolView : UIView 18 19 //塊變量類型的setter方法 20 -(void)setToolIndex:(ToolIndex) toolBlock; 21 22 @end
ToolView.m的代碼實現:
1 // 2 // ToolView.m 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 #import "ToolView.h" 10 11 @interface ToolView () 12 13 //定義ToolIndex類型的block,用於接受外界傳過來的block 14 @property (nonatomic, strong) ToolIndex myBlock; 15 16 @end 17 18 19 @implementation ToolView 20 21 - (id)initWithFrame:(CGRect)frame 22 { 23 self = [super initWithFrame:frame]; 24 if (self) { 25 26 //1初始化表情按鈕 27 UIButton *faceButton = [[UIButton alloc] initWithFrame:CGRectZero]; 28 faceButton.backgroundColor = [UIColor orangeColor]; 29 [faceButton setTitle:@"表情" forState:UIControlStateNormal]; 30 [faceButton setShowsTouchWhenHighlighted:YES]; 31 [faceButton addTarget:self action:@selector(tapFaceButton:) forControlEvents:UIControlEventTouchUpInside]; 32 [self addSubview:faceButton]; 33 34 35 //初始化更多按鈕 36 UIButton *moreButton = [[UIButton alloc] initWithFrame:CGRectZero]; 37 moreButton.backgroundColor = [UIColor grayColor]; 38 [moreButton setTitle:@"More" forState:UIControlStateNormal]; 39 [moreButton setShowsTouchWhenHighlighted:YES]; 40 [moreButton addTarget:self action:@selector(tapMoreButton:) forControlEvents:UIControlEventTouchUpInside]; 41 [self addSubview:moreButton]; 42 43 44 //給咱們的按鈕添加約束來讓按鈕來佔滿toolView; 45 faceButton.translatesAutoresizingMaskIntoConstraints = NO; 46 moreButton.translatesAutoresizingMaskIntoConstraints = NO; 47 48 //添加水平約束 49 NSArray *buttonH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[faceButton][moreButton(==faceButton)]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(faceButton,moreButton)]; 50 [self addConstraints:buttonH]; 51 52 //添加垂直約束 53 NSArray *button1V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[faceButton]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(faceButton)]; 54 [self addConstraints:button1V]; 55 56 NSArray *button2V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[moreButton]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(moreButton)]; 57 [self addConstraints:button2V]; 58 59 } 60 return self; 61 } 62 63 //接受傳入的回調 64 -(void) setToolIndex:(ToolIndex)toolBlock 65 { 66 self.myBlock = toolBlock; 67 } 68 69 //點擊表情按鈕要回調的方法 70 -(void) tapFaceButton: (id) sender 71 { 72 self.myBlock(1); 73 } 74 75 //點擊more要回調的方法 76 -(void) tapMoreButton: (id) sender 77 { 78 self.myBlock(2); 79 } 80 81 @end
代碼說明:
主要是對block回調的應用和給相應的組件添加相應的約束
4.MoreView組件的封裝代碼就不往上貼啦,和上面的相似,下面是調用MoreView組件的運行效果,有興趣的讀者請自行編寫,以上就是視圖部分的代碼了
二. Mode部分的內容:
1.先定義咱們要使用的數據模型,數據模型以下,time是使用表情的時間,用於排序。
2.下面編寫咱們的ImageModelClass類,裏面封裝了咱們操做數據要用的方法
ImageModelClass.h的代碼以下,主要是預留的對外的接口:
1 // 2 // ImageModelClass.h 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import <CoreData/CoreData.h> 11 #import "HistoryImage.h" 12 13 @interface ImageModelClass : NSObject 14 //保存數據 15 -(void)save:(NSData *) image ImageText:(NSString *) imageText; 16 //查詢全部的圖片 17 -(NSArray *) queryAll; 18 @end
ImageModelClass.m的代碼以下,主要是用CoreData對sqlite的操做:
1 // 2 // ImageModelClass.m 3 // MyKeyBoard 4 // 5 // Created by 青玉伏案 on 14-9-16. 6 // Copyright (c) 2014年 Mrli. All rights reserved. 7 // 8 9 #import "ImageModelClass.h" 10 11 @interface ImageModelClass () 12 13 @property (nonatomic, strong) NSManagedObjectContext *manager; 14 15 @end 16 17 @implementation ImageModelClass 18 - (instancetype)init 19 { 20 self = [super init]; 21 if (self) { 22 //經過上下文獲取manager 23 UIApplication *application = [UIApplication sharedApplication]; 24 id delegate = application.delegate; 25 self.manager = [delegate managedObjectContext]; 26 } 27 return self; 28 } 29 30 -(void)save:(NSData *)image ImageText:(NSString *)imageText 31 { 32 if (image != nil) { 33 NSArray *result = [self search:imageText]; 34 35 HistoryImage *myImage; 36 37 if (result.count == 0) 38 { 39 myImage = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([HistoryImage class]) inManagedObjectContext:self.manager]; 40 myImage.imageText = imageText; 41 myImage.headerImage = image; 42 myImage.time = [NSDate date]; 43 } 44 else 45 { 46 myImage = result[0]; 47 myImage.time = [NSDate date]; 48 } 49 50 //存儲實體 51 NSError *error = nil; 52 if (![self.manager save:&error]) { 53 NSLog(@"保存出錯%@", [error localizedDescription]); 54 } 55 56 } 57 58 } 59 60 61 //查找 62 -(NSArray *)search:(NSString *) image 63 { 64 NSArray *result; 65 66 //新建查詢條件 67 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([HistoryImage class])]; 68 69 //添加謂詞 70 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"imageText=%@",image]; 71 72 //把謂詞給request 73 [fetchRequest setPredicate:predicate]; 74 75 //執行查詢 76 NSError *error = nil; 77 result = [self.manager executeFetchRequest:fetchRequest error:&error]; 78 if (error) { 79 NSLog(@"查詢錯誤:%@", [error localizedDescription]); 80 } 81 return result; 82 } 83 84 85 86 //查詢全部的 87 -(NSArray *) queryAll 88 { 89 //新建查詢條件 90 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([HistoryImage class])]; 91 92 //添加排序規則 93 //定義排序規則 94 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"time" ascending:NO]; 95 96 //添加排序規則 97 [fetchRequest setSortDescriptors:@[sortDescriptor]]; 98 99 100 //執行查詢 101 NSError *error = nil; 102 NSArray *result = [self.manager executeFetchRequest:fetchRequest error:&error]; 103 if (error) { 104 NSLog(@"查詢錯誤:%@", [error localizedDescription]); 105 } 106 107 return result; 108 } 109 110 @end
代碼說明:
1.保存圖片時先查找圖片是否存在,若是存在則更新時間,若是不存在則插入數據(寫到這感受想在用Hibernate寫東西)。
三.Controller部分,把上面的組件進行組裝
1.MainViewController.m中的延展部分的代碼以下:
1 @interface MainViewController () 2 3 //自定義組件 4 @property (nonatomic, strong) ToolView *toolView; 5 6 @property (nonatomic, strong) FunctionView *functionView; 7 8 @property (nonatomic, strong) MoreView *moreView; 9 10 //系統組件 11 @property (strong, nonatomic) IBOutlet UITextView *myTextView; 12 13 @property (strong, nonatomic) NSDictionary *keyBoardDic; 14 15 @property (strong, nonatomic) IBOutlet UIImageView *imageView; 16 17 @property (strong, nonatomic) NSString *sendString; 18 19 //數據model 20 @property (strong, nonatomic) ImageModelClass *imageMode; 21 22 @property (strong, nonatomic)HistoryImage *tempImage; 23 24 @end
2.在viewDidLoad中進行組件的初始化和實現組件的Block回調,代碼以下
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 //從sqlite中讀取數據 6 self.imageMode = [[ImageModelClass alloc] init]; 7 8 9 //實例化FunctionView 10 self.functionView = [[FunctionView alloc] initWithFrame:CGRectMake(0, 0, 320, 216)]; 11 self.functionView.backgroundColor = [UIColor blackColor]; 12 13 //設置資源加載的文件名 14 self.functionView.plistFileName = @"emoticons"; 15 16 __weak __block MainViewController *copy_self = self; 17 //獲取圖片並顯示 18 [self.functionView setFunctionBlock:^(UIImage *image, NSString *imageText) 19 { 20 NSString *str = [NSString stringWithFormat:@"%@%@",copy_self.myTextView.text, imageText]; 21 22 copy_self.myTextView.text = str; 23 copy_self.imageView.image = image; 24 25 //把使用過的圖片存入sqlite 26 NSData *imageData = UIImagePNGRepresentation(image); 27 [copy_self.imageMode save:imageData ImageText:imageText]; 28 }]; 29 30 31 //實例化MoreView 32 self.moreView = [[MoreView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; 33 self.moreView.backgroundColor = [UIColor blackColor]; 34 [self.moreView setMoreBlock:^(NSInteger index) { 35 NSLog(@"MoreIndex = %d",index); 36 }]; 37 38 39 40 //進行ToolView的實例化 41 self.toolView = [[ToolView alloc] initWithFrame:CGRectZero]; 42 self.toolView.backgroundColor = [UIColor blackColor]; 43 [self.view addSubview:self.toolView]; 44 45 //給ToolView添加約束 46 //開啓自動佈局 47 self.toolView.translatesAutoresizingMaskIntoConstraints = NO; 48 49 //水平約束 50 NSArray *toolHConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_toolView]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(_toolView)]; 51 [self.view addConstraints:toolHConstraint]; 52 53 //垂直約束 54 NSArray *toolVConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_toolView(44)]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(_toolView)]; 55 [self.view addConstraints:toolVConstraint]; 56 57 58 59 60 //回調toolView中的方法 61 [self.toolView setToolIndex:^(NSInteger index) 62 { 63 NSLog(@"%d", index); 64 65 switch (index) { 66 case 1: 67 [copy_self changeKeyboardToFunction]; 68 break; 69 70 case 2: 71 [copy_self changeKeyboardToMore]; 72 break; 73 74 default: 75 break; 76 } 77 78 }]; 79 80 81 82 //當鍵盤出來的時候經過通知來獲取鍵盤的信息 83 //註冊爲鍵盤的監聽着 84 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 85 [center addObserver:self selector:@selector(keyNotification:) name:UIKeyboardWillChangeFrameNotification object:nil]; 86 87 88 //給鍵盤添加dan 89 //TextView的鍵盤定製回收按鈕 90 UIToolbar * toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 30)]; 91 92 UIBarButtonItem * item1 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(tapDone:)]; 93 UIBarButtonItem * item2 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 94 UIBarButtonItem * item3 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 95 toolBar.items = @[item2,item1,item3]; 96 97 self.myTextView.inputAccessoryView =toolBar; 98 99 }
3.當橫豎屏幕切換時設置自定義鍵盤的高度
1 -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 2 { 3 //縱屏 4 if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) { 5 CGRect frame = self.functionView.frame; 6 frame.size.height = 216; 7 self.functionView.frame = frame; 8 self.moreView.frame = frame; 9 10 } 11 //橫屏 12 if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) { 13 CGRect frame = self.functionView.frame; 14 frame.size.height = 150; 15 self.functionView.frame = frame; 16 self.moreView.frame = frame; 17 } 18 }
4.當鍵盤出來的時候,改變toolView的位置,經過鍵盤的通知來實現。當橫屏的時候鍵盤的座標系和咱們當前的Frame的座標系不同因此當橫屏時得作一座標系的轉換,代碼以下;
1 //當鍵盤出來的時候改變toolView的位置(接到鍵盤出來的通知要作的方法) 2 -(void) keyNotification : (NSNotification *) notification 3 { 4 NSLog(@"%@", notification.userInfo); 5 6 self.keyBoardDic = notification.userInfo; 7 //獲取鍵盤移動後的座標點的座標點 8 CGRect rect = [self.keyBoardDic[@"UIKeyboardFrameEndUserInfoKey"] CGRectValue]; 9 10 //把鍵盤的座標系改爲當前咱們window的座標系 11 CGRect r1 = [self.view convertRect:rect fromView:self.view.window]; 12 13 [UIView animateWithDuration:[self.keyBoardDic[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{ 14 15 //動畫曲線 16 [UIView setAnimationCurve:[self.keyBoardDic[UIKeyboardAnimationCurveUserInfoKey] doubleValue]]; 17 18 CGRect frame = self.toolView.frame; 19 20 frame.origin.y = r1.origin.y - frame.size.height; 21 22 //根據鍵盤的高度來改變toolView的高度 23 self.toolView.frame = frame; 24 }]; 25 }
5.系統鍵盤和自定義鍵盤切換的代碼以下:
1 //切換鍵盤的方法 2 -(void) changeKeyboardToFunction 3 { 4 if ([self.myTextView.inputView isEqual:self.functionView]) 5 { 6 self.myTextView.inputView = nil; 7 [self.myTextView reloadInputViews]; 8 } 9 else 10 { 11 self.myTextView.inputView = self.functionView; 12 [self.myTextView reloadInputViews]; 13 } 14 15 if (![self.myTextView isFirstResponder]) 16 { 17 [self.myTextView becomeFirstResponder]; 18 } 19 }
以上就是上面展現效果的核心代碼了,在作的時候感受難點在於如何進行屏幕適配,尤爲是當屏幕橫過來的時候鍵盤的座標系和咱們frame的座標系不一樣,得作一個轉換。發表博客的目的是想起到拋磚引玉的做用,有好的東西但願你們相互交流一下。筆者水平有限不免有偏頗之處,歡迎批評指正。