上面是文件的组织结构,下面为了更为直观的了解我们想要的效果,下面先看几张截图,来直观的感受一下运行效果,上面是竖屏的显示效果,下面是横屏的显示效果。因为在封装自定义键盘中用到了自动布局所以横屏显示或者在更大的屏幕上显示是没问题的,常用表情是用户用过的表情,然后存在Sqlite中,显示时并按时间降序排列。more是用来扩展功能用的接口。话不多说,来的代码才是实在的。
一.View(自定义视图)
View文件夹下存放的时我们自定义的视图组件,因为是自定义的组件所以storyboard我们就用不了啦,所有的代码都必须手写,这样才能保证组件使用的灵活性和减少各个组件之间的耦合性,更利于团队之间的合作。在封装组件时要预留好外界可能使用到的接口,和返回该返回的数据。好啦,废话少说,来点干货吧!
1、FaceView组件的封装:FaceView即负责显示一个个的头像。在使用该组件时要传入要显示的图片和图片对应的文字(如【哈哈】),当点击图片的时候,会通过block回调的形式把该图片的image以及图片文字返回到使用的组件中去,下面是关键代码:
FaceView.h中的代码如下(下面代码是定义啦相应的Block类型和对外的接口):
FaceView.m中的代码如下
代码说明:
主要就是block回调的使用,就是封装了一个自定义的button,具体内容请参考之前的博客“IOS开发之自定义Button(集成三种回调模式)”
2、FunctionView组件的封装,FunctionView就是使用FaceView组件和ScrollView组件把表情加载进来,在实例化FunctionView组件时,我们用到了自动布局来设置ScrollView和下面的Button
FunctionView.h的代码如下,在.h中留有组件的接口和回调用的Block, plistFileName用于加载我们的资源文件时使用,至于如何使用plist文件,请参考之前的博客:IOS开发之显示微博表情
FunctionView.m中的代码如下,常用表情是在sqlite中获取的,而全部表情是通过plist文件的信息在Face文件中加载的:
代码说明:
1、主要是通过对资源文件或者对从数据库中查询的资源进行遍历然后添加到ScrollView中
2.为了适应不同的屏幕给相应的组件添加了约束
3.ToolView组件的封装: ToolView就是在主屏幕上下面的类似于TabBar的东西,当键盘出来的时候,ToolView会运动到键盘上面的位置。为了使用不同的屏幕,也需要用自动布局来实现。
ToolView.h的代码如下:预留组件接口和声明block类型
ToolView.m的代码实现:
代码说明:
主要是对block回调的应用和给相应的组件添加相应的约束
4.MoreView组件的封装代码就不往上贴啦,和上面的类似,下面是调用MoreView组件的运行效果,有兴趣的读者请自行编写,以上就是视图部分的代码了
二. Mode部分的内容:
1.先定义我们要使用的数据模型,数据模型如下,time是使用表情的时间,用于排序。
2.下面编写我们的ImageModelClass类,里面封装了我们操作数据要用的方法
ImageModelClass.h的代码如下,主要是预留的对外的接口:
ImageModelClass.m的代码如下,主要是用CoreData对sqlite的操作:
代码说明:
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 }