服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS组件封装与自动布局自定义表情键盘

iOS组件封装与自动布局自定义表情键盘

2021-01-17 20:40iOS开发网 IOS

这篇文章主要介绍了iOS组件封装与自动布局自定义表情键盘的相关资料,需要的朋友可以参考下

下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有mvc, ios开发中的自动布局,自定义组件的封装与使用,block回调,coredata的使用。有的小伙伴可能会问写一个自定义表情键盘肿么这么麻烦?下面 将会介绍我们如何用上面提到的东西来定义我们的表情键盘的。下面的内容会比较多,这篇文章还是比较有料的。

还是那句话写技术博客是少不了代码的,下面会结合代码来回顾一下ios的知识,本篇博文中用到的知识点在前面的博客中都能找到相应的内容,本篇 算是一个小小的功能整合。先来张图看一下本app的目录结构。我是根据自己对mvc的理解来构建的目录结构,希望起到抛砖引玉的作用,有好的解决方案欢迎 评论或者留言指出。face文件中存放的时我们的表情图片,model文件封装的是从sqlite中读取历史头像的组件,view文件中封装的时我们自定义的组件,也就是自定义键盘相关的视图,controller负责将我们的各个组件组装到一起完成我们想要的功能。下面会一一介绍。

iOS组件封装与自动布局自定义表情键盘

上面是文件的组织结构,下面为了更为直观的了解我们想要的效果,下面先看几张截图,来直观的感受一下运行效果,上面是竖屏的显示效果,下面是横 屏的显示效果。因为在封装自定义键盘中用到了自动布局所以横屏显示或者在更大的屏幕上显示是没问题的,常用表情是用户用过的表情,然后存在sqlite 中,显示时并按时间降序排列。more是用来扩展功能用的接口。话不多说,来的代码才是实在的。

iOS组件封装与自动布局自定义表情键盘

一.view(自定义视图)

view文件夹下存放的时我们自定义的视图组件,因为是自定义的组件所以storyboard我们就用不了啦,所有的代码都必须手写,这样 才能保证组件使用的灵活性和减少各个组件之间的耦合性,更利于团队之间的合作。在封装组件时要预留好外界可能使用到的接口,和返回该返回的数据。好啦,废话少说,来点干货吧!

1、faceview组件的封装:faceview即负责显示一个个的头像。在使用该组件时要传入要显示的图片和图片对应的文字(如【哈 哈】),当点击图片的时候,会通过block回调的形式把该图片的image以及图片文字返回到使用的组件中去,下面是关键代码:

faceview.h中的代码如下(下面代码是定义啦相应的block类型和对外的接口):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import //声明表情对应的block,用于把点击的表情的图片和图片信息传到上层视图
typedef void (^faceblock) (uiimage *image, nsstring *imagetext);
 
@interface faceview : uiview
 
//图片对应的文字
@property (nonatomic, strong) nsstring *imagetext;
//表情图片
@property (nonatomic, strong) uiimage *headerimage;
 
//设置block回调
-(void)setfaceblock:(faceblock)block;
 
//设置图片,文字
-(void)setimage:(uiimage *) image imagetext:(nsstring *) text;
 
@end

faceview.m中的代码如下

?
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
// faceview.m
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
#import "faceview.h"
 
@interface faceview ()
@property(strong, nonatomic) faceblock block;
@property (strong, nonatomic) uiimageview *imageview;
@end
 
@implementation faceview
 
//初始化图片
- (id)initwithframe:(cgrect)frame
{
 //face的大小
 frame.size.height = 30;
 frame.size.width = 30;
 self = [super initwithframe:frame];
 if (self) {
 self.imageview = [[uiimageview alloc] initwithframe:cgrectmake(0, 0, 30, 30)];
 [self addsubview:self.imageview];
 }
 return self;
}
 
-(void) setfaceblock:(faceblock)block
{
 self.block = block;
}
 
 
-(void) setimage:(uiimage *)image imagetext:(nsstring *)text
{
 //显示图片
 [self.imageview setimage:image];
 
 //把图片存储起来
 self.headerimage = image;
 
 self.imagetext = text;
}
 
//点击时回调
-(void)touchesended:(nsset *)touches withevent:(uievent *)event
{
 uitouch *touch = [touches anyobject];
 cgpoint point = [touch locationinview:self];
 //判断触摸的结束点是否在图片中
 if (cgrectcontainspoint(self.bounds, point))
 {
 //回调,把该头像的信息传到相应的controller中
 self.block(self.headerimage, self.imagetext);
 }
}
 
@end

代码说明:

主要就是block回调的使用,就是封装了一个自定义的button

2、functionview组件的封装,functionview就是使用faceview组件和scrollview组件把表情加载进来,在实例化functionview组件时,我们用到了自动布局来设置scrollview和下面的button.

functionview.h的代码如下,在.h中留有组件的接口和回调用的block, plistfilename用于加载我们的资源文件时使用。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// functionview.h
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
#import //定义对应的block类型,用于数据的交互
typedef void (^functionblock) (uiimage *image, nsstring *imagetext);
 
@interface functionview : uiview
//资源文件名
@property (nonatomic, strong) nsstring *plistfilename;
//接受block块
-(void)setfunctionblock:(functionblock) block;
 
@end

functionview.m中的代码如下,常用表情是在sqlite中获取的,而全部表情是通过plist文件的信息在face文件中加载的:

?
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
// functionview.m
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
#import "functionview.h"
#import "faceview.h"
#import "imagemodelclass.h"
#import "historyimage.h"
 
@interface functionview()
 
@property (strong, nonatomic) functionblock block;
//暂存表情组件回调的表情和表情文字
@property (strong, nonatomic) uiimage *headerimage;
@property (strong, nonatomic) nsstring *imagetext;
 
//display我们的表情图片
@property (strong, nonatomic) uiscrollview *headerscrollview;
 
//定义数据模型用于获取历史表情
@property (strong, nonatomic) imagemodelclass *imagemodel;
 
@end
 
 
@implementation functionview
- (id)initwithframe:(cgrect)frame
{
 self = [super initwithframe:frame];
 if (self) {
 
 //实例化数据模型
 self.imagemodel =[[imagemodelclass alloc] init];
 
 //实例化下面的button
 uibutton *facebutton = [[uibutton alloc] initwithframe:cgrectzero];
 facebutton.backgroundcolor = [uicolor graycolor];
 
 [facebutton settitle:@"全部表情" forstate:uicontrolstatenormal];
 [facebutton setshowstouchwhenhighlighted:yes];
 [facebutton addtarget:self action:@selector(tapbutton1:) forcontrolevents:uicontroleventtouchupinside];
 [self addsubview:facebutton];
 
 
 //实例化常用表情按钮
 uibutton *morebutton = [[uibutton alloc] initwithframe:cgrectzero];
 morebutton.backgroundcolor = [uicolor orangecolor];
 [morebutton settitle:@"常用表情" forstate:uicontrolstatenormal];
 [morebutton setshowstouchwhenhighlighted:yes];
 [morebutton addtarget:self action:@selector(tapbutton2:) forcontrolevents:uicontroleventtouchupinside];
 [self addsubview:morebutton];
 
 //给按钮添加约束
 facebutton.translatesautoresizingmaskintoconstraints = no;
 morebutton.translatesautoresizingmaskintoconstraints = no;
 //水平约束
 nsarray *buttonh = [nslayoutconstraint constraintswithvisualformat:@"h:|[facebutton][morebutton(==facebutton)]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(facebutton,morebutton)];
 [self addconstraints:buttonh];
 
 //垂直约束
 nsarray *button1v = [nslayoutconstraint constraintswithvisualformat:@"v:[facebutton(44)]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(facebutton)];
 [self addconstraints:button1v];
 
 nsarray *button2v = [nslayoutconstraint constraintswithvisualformat:@"v:[morebutton(44)]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(morebutton)];
 [self addconstraints:button2v];
 
 //默认显示表情图片
 [self tapbutton1:nil];
 
 }
 return self;
}
 
//接受回调
-(void)setfunctionblock:(functionblock)block
{
 self.block = block;
}
 
//点击全部表情按钮回调方法
-(void)tapbutton1: (id) sender
{
 // 从plist文件载入资源
 nsbundle *bundle = [nsbundle mainbundle];
 nsstring *path = [bundle pathforresource:self.plistfilename oftype:@"plist"];
 nsarray *headers = [nsarray arraywithcontentsoffile:path];
 
 if (headers.count == 0) {
 nslog(@"访问的plist文件不存在");
 }
 else
 {
 //调用headers方法显示表情
 [self header:headers];
 }
}
 
//点击历史表情的回调方法
-(void) tapbutton2: (id) sender
{
 //从数据库中查询所有的图片
 nsarray *imagedata = [self.imagemodel queryall];
 //解析请求到的数据
 nsmutablearray *headers = [nsmutablearray arraywithcapacity:imagedata.count];
 
 //数据实体,相当于javabean的东西
 historyimage *tempdata;
 
 for (int i = 0; i < imagedata.count; i ++) {
 tempdata = imagedata[i];
 
 //解析数据,转换成函数headers要用的数据格式
 nsmutabledictionary *dic = [nsmutabledictionary dictionarywithcapacity:2];
 [dic setobject:tempdata.imagetext forkey:@"chs"];
 uiimage *image = [uiimage imagewithdata:tempdata.headerimage];
 [dic setobject:image forkey:@"png"];
 
 [headers addobject:dic];
 }
 
 [self header:headers];
 
}
 
 
//负责把查出来的图片显示
-(void) header:(nsarray *)headers
{
 [self.headerscrollview removefromsuperview];
 self.headerscrollview = [[uiscrollview alloc] initwithframe:cgrectzero];
 [self addsubview:self.headerscrollview];
 
 //给scrollview添加约束
 self.headerscrollview.translatesautoresizingmaskintoconstraints = no;
 //水平约束
 nsarray *scrollh = [nslayoutconstraint constraintswithvisualformat:@"h:|-10-[_headerscrollview]-10-|" options:0 metrics:0 views:nsdictionaryofvariablebindings(_headerscrollview)];
 [self addconstraints:scrollh];
 
 //垂直约束
 nsarray *scrolv = [nslayoutconstraint constraintswithvisualformat:@"v:|-10-[_headerscrollview]-50-|" options:0 metrics:0 views:nsdictionaryofvariablebindings(_headerscrollview)];
 [self addconstraints:scrolv];
 
 
 
 cgfloat scrollheight = (self.frame).size.height-60;
 
 //根据图片量来计算scrollview的contain的宽度
 cgfloat width = (headers.count/(scrollheight/30))*30;
 self.headerscrollview.contentsize = cgsizemake(width, scrollheight);
 self.headerscrollview.pagingenabled = yes;
 
 
 //图片坐标
 cgfloat x = 0;
 cgfloat y = 0;
 
 //往scroll上贴图片
 for (int i = 0; i < headers.count; i ++) {
 //获取图片信息
 uiimage *image;
 if ([headers[i][@"png"] iskindofclass:[nsstring class]])
 {
 image = [uiimage imagenamed:headers[i][@"png"]];
 }
 else
 {
 image = headers[i][@"png"];
 }
 
 nsstring *imagetext = headers[i][@"chs"];
 
 //计算图片位置
 y = (i%(int)(scrollheight/30)) * 30;
 x = (i/(int)(scrollheight/30)) * 30;
 
 faceview *face = [[faceview alloc] initwithframe:cgrectmake(x, y, 0, 0)];
 [face setimage:image imagetext:imagetext];
 
 //face的回调,当face点击时获取face的图片
 __weak __block functionview *copy_self = self;
 [face setfaceblock:^(uiimage *image, nsstring *imagetext)
 {
 copy_self.block(image, imagetext);
 }];
 
 [self.headerscrollview addsubview:face];
 }
 
 [self.headerscrollview setneedsdisplay];
 
}
 
@end

代码说明:

1、主要是通过对资源文件或者对从数据库中查询的资源进行遍历然后添加到scrollview中

2.为了适应不同的屏幕给相应的组件添加了约束

3.toolview组件的封装: toolview就是在主屏幕上下面的类似于tabbar的东西,当键盘出来的时候,toolview会运动到键盘上面的位置。为了使用不同的屏幕,也需要用自动布局来实现。

toolview.h的代码如下:预留组件接口和声明block类型

?
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
// toolview.h
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
/*****************
 封装下面的工具条组件
 *****************/
#import //定义block块变量类型,用于回调,把本view上的按钮的index传到controller中
typedef void (^toolindex) (nsinteger index);
 
@interface toolview : uiview
 
//块变量类型的setter方法
-(void)settoolindex:(toolindex) toolblock;
 
@end
toolview.m的代码实现:
// toolview.m
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
#import "toolview.h"
 
@interface toolview ()
 
//定义toolindex类型的block,用于接受外界传过来的block
@property (nonatomic, strong) toolindex myblock;
 
@end
 
 
@implementation toolview
 
- (id)initwithframe:(cgrect)frame
{
 self = [super initwithframe:frame];
 if (self) {
 
 //1初始化表情按钮
 uibutton *facebutton = [[uibutton alloc] initwithframe:cgrectzero];
 facebutton.backgroundcolor = [uicolor orangecolor];
 [facebutton settitle:@"表情" forstate:uicontrolstatenormal];
 [facebutton setshowstouchwhenhighlighted:yes];
 [facebutton addtarget:self action:@selector(tapfacebutton:) forcontrolevents:uicontroleventtouchupinside];
 [self addsubview:facebutton];
 
 
 //初始化更多按钮
 uibutton *morebutton = [[uibutton alloc] initwithframe:cgrectzero];
 morebutton.backgroundcolor = [uicolor graycolor];
 [morebutton settitle:@"more" forstate:uicontrolstatenormal];
 [morebutton setshowstouchwhenhighlighted:yes];
 [morebutton addtarget:self action:@selector(tapmorebutton:) forcontrolevents:uicontroleventtouchupinside];
 [self addsubview:morebutton];
 
 
 //给我们的按钮添加约束来让按钮来占满toolview;
 facebutton.translatesautoresizingmaskintoconstraints = no;
 morebutton.translatesautoresizingmaskintoconstraints = no;
 
 //添加水平约束
 nsarray *buttonh = [nslayoutconstraint constraintswithvisualformat:@"h:|[facebutton][morebutton(==facebutton)]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(facebutton,morebutton)];
 [self addconstraints:buttonh];
 
 //添加垂直约束
 nsarray *button1v = [nslayoutconstraint constraintswithvisualformat:@"v:|[facebutton]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(facebutton)];
 [self addconstraints:button1v];
 
 nsarray *button2v = [nslayoutconstraint constraintswithvisualformat:@"v:|[morebutton]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(morebutton)];
 [self addconstraints:button2v];
 
 }
 return self;
}
 
//接受传入的回调
-(void) settoolindex:(toolindex)toolblock
{
 self.myblock = toolblock;
}
 
//点击表情按钮要回调的方法
-(void) tapfacebutton: (id) sender
{
 self.myblock(1);
}
 
//点击more要回调的方法
-(void) tapmorebutton: (id) sender
{
 self.myblock(2);
}
 
@end

代码说明:

主要是对block回调的应用和给相应的组件添加相应的约束。

4.moreview组件的封装代码就不往上贴啦,和上面的类似,下面是调用moreview组件的运行效果,有兴趣的读者请自行编写,以上就是视图部分的代码了

iOS组件封装与自动布局自定义表情键盘

二. mode部分的内容

1.先定义我们要使用的数据模型,数据模型如下,time是使用表情的时间,用于排序。

iOS组件封装与自动布局自定义表情键盘

2.下面编写我们的imagemodelclass类,里面封装了我们操作数据要用的方法

imagemodelclass.h的代码如下,主要是预留的对外的接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
// imagemodelclass.h
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
#import #import #import "historyimage.h"
 
@interface imagemodelclass : nsobject
//保存数据
-(void)save:(nsdata *) image imagetext:(nsstring *) imagetext;
//查询所有的图片
-(nsarray *) queryall;
@end

imagemodelclass.m的代码如下,主要是用coredata对sqlite的操作:

?
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
// imagemodelclass.m
// mykeyboard
//
// created by 青玉伏案 on 14-9-16.
// copyright (c) 2014年 mrli. all rights reserved.
//
 
#import "imagemodelclass.h"
 
@interface imagemodelclass ()
 
@property (nonatomic, strong) nsmanagedobjectcontext *manager;
 
@end
 
@implementation imagemodelclass
- (instancetype)init
{
 self = [super init];
 if (self) {
 //通过上下文获取manager
 uiapplication *application = [uiapplication sharedapplication];
 id delegate = application.delegate;
 self.manager = [delegate managedobjectcontext];
 }
 return self;
}
 
-(void)save:(nsdata *)image imagetext:(nsstring *)imagetext
{
 if (image != nil) {
 nsarray *result = [self search:imagetext];
 
 historyimage *myimage;
 
 if (result.count == 0)
 {
 myimage = [nsentitydescription insertnewobjectforentityforname:nsstringfromclass([historyimage class]) inmanagedobjectcontext:self.manager];
 myimage.imagetext = imagetext;
 myimage.headerimage = image;
 myimage.time = [nsdate date];
 }
 else
 {
 myimage = result[0];
 myimage.time = [nsdate date];
 }
 
 //存储实体
 nserror *error = nil;
 if (![self.manager save:&error]) {
 nslog(@"保存出错%@", [error localizeddescription]);
 }
 
 }
 
}
 
 
//查找
-(nsarray *)search:(nsstring *) image
{
 nsarray *result;
 
 //新建查询条件
 nsfetchrequest *fetchrequest = [[nsfetchrequest alloc] initwithentityname:nsstringfromclass([historyimage class])];
 
 //添加谓词
 nspredicate *predicate = [nspredicate predicatewithformat:@"imagetext=%@",image];
 
 //把谓词给request
 [fetchrequest setpredicate:predicate];
 
 //执行查询
 nserror *error = nil;
 result = [self.manager executefetchrequest:fetchrequest error:&error];
 if (error) {
 nslog(@"查询错误:%@", [error localizeddescription]);
 }
 return result;
}
 
 
 
//查询所有的
-(nsarray *) queryall
{
 //新建查询条件
 nsfetchrequest *fetchrequest = [[nsfetchrequest alloc] initwithentityname:nsstringfromclass([historyimage class])];
 
 //添加排序规则
 //定义排序规则
 nssortdescriptor *sortdescriptor = [[nssortdescriptor alloc] initwithkey:@"time" ascending:no];
 
 //添加排序规则
 [fetchrequest setsortdescriptors:@[sortdescriptor]];
 
 
 //执行查询
 nserror *error = nil;
 nsarray *result = [self.manager executefetchrequest:fetchrequest error:&error];
 if (error) {
 nslog(@"查询错误:%@", [error localizeddescription]);
 }
 
 return result;
}
 
@end

代码说明:

1.保存图片时先查找图片是否存在,如果存在则更新时间,如果不存在则插入数据(写到这感觉想在用hibernate写东西)。

三.controller部分,把上面的组件进行组装

1.mainviewcontroller.m中的延展部分的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@interface mainviewcontroller ()
 
//自定义组件
@property (nonatomic, strong) toolview *toolview;
 
@property (nonatomic, strong) functionview *functionview;
 
@property (nonatomic, strong) moreview *moreview;
 
//系统组件
@property (strong, nonatomic) iboutlet uitextview *mytextview;
 
@property (strong, nonatomic) nsdictionary *keyboarddic;
 
@property (strong, nonatomic) iboutlet uiimageview *imageview;
 
@property (strong, nonatomic) nsstring *sendstring;
 
//数据model
@property (strong, nonatomic) imagemodelclass *imagemode;
 
@property (strong, nonatomic)historyimage *tempimage;
 
@end

2.在viewdidload中进行组件的初始化和实现组件的block回调,代码如下

?
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
- (void)viewdidload
{
 [super viewdidload];
 
 //从sqlite中读取数据
 self.imagemode = [[imagemodelclass alloc] init];
 
 
 //实例化functionview
 self.functionview = [[functionview alloc] initwithframe:cgrectmake(0, 0, 320, 216)];
 self.functionview.backgroundcolor = [uicolor blackcolor];
 
 //设置资源加载的文件名
 self.functionview.plistfilename = @"emoticons";
 
 __weak __block mainviewcontroller *copy_self = self;
 //获取图片并显示
 [self.functionview setfunctionblock:^(uiimage *image, nsstring *imagetext)
 {
 nsstring *str = [nsstring stringwithformat:@"%@%@",copy_self.mytextview.text, imagetext];
 
 copy_self.mytextview.text = str;
 copy_self.imageview.image = image;
 
 //把使用过的图片存入sqlite
 nsdata *imagedata = uiimagepngrepresentation(image);
 [copy_self.imagemode save:imagedata imagetext:imagetext];
 }];
 
 
 //实例化moreview
 self.moreview = [[moreview alloc] initwithframe:cgrectmake(0, 0, 0, 0)];
 self.moreview.backgroundcolor = [uicolor blackcolor];
 [self.moreview setmoreblock:^(nsinteger index) {
 nslog(@"moreindex = %d",index);
 }];
 
 
 
 //进行toolview的实例化
 self.toolview = [[toolview alloc] initwithframe:cgrectzero];
 self.toolview.backgroundcolor = [uicolor blackcolor];
 [self.view addsubview:self.toolview];
 
 //给toolview添加约束
 //开启自动布局
 self.toolview.translatesautoresizingmaskintoconstraints = no;
 
 //水平约束
 nsarray *toolhconstraint = [nslayoutconstraint constraintswithvisualformat:@"h:|[_toolview]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(_toolview)];
 [self.view addconstraints:toolhconstraint];
 
 //垂直约束
 nsarray *toolvconstraint = [nslayoutconstraint constraintswithvisualformat:@"v:[_toolview(44)]|" options:0 metrics:0 views:nsdictionaryofvariablebindings(_toolview)];
 [self.view addconstraints:toolvconstraint];
 
 
 
 
 //回调toolview中的方法
 [self.toolview settoolindex:^(nsinteger index)
 {
 nslog(@"%d", index);
 
 switch (index) {
 case 1:
 [copy_self changekeyboardtofunction];
 break;
  
 case 2:
 [copy_self changekeyboardtomore];
 break;
  
 default:
 break;
 }
 
 }];
 
 
 
 //当键盘出来的时候通过通知来获取键盘的信息
 //注册为键盘的监听着
 nsnotificationcenter *center = [nsnotificationcenter defaultcenter];
 [center addobserver:self selector:@selector(keynotification:) name:uikeyboardwillchangeframenotification object:nil];
 
 
 //给键盘添加dan
 //textview的键盘定制回收按钮
 uitoolbar * toolbar = [[uitoolbar alloc]initwithframe:cgrectmake(0, 0, 320, 30)];
 
 uibarbuttonitem * item1 = [[uibarbuttonitem alloc]initwithbarbuttonsystemitem:uibarbuttonsystemitemdone target:self action:@selector(tapdone:)];
 uibarbuttonitem * item2 = [[uibarbuttonitem alloc]initwithbarbuttonsystemitem:uibarbuttonsystemitemflexiblespace target:nil action:nil];
 uibarbuttonitem * item3 = [[uibarbuttonitem alloc]initwithbarbuttonsystemitem:uibarbuttonsystemitemflexiblespace target:nil action:nil];
 toolbar.items = @[item2,item1,item3];
 
 self.mytextview.inputaccessoryview =toolbar;
 
}

3.当横竖屏幕切换时设置自定义键盘的高度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-(void)willanimaterotationtointerfaceorientation:(uiinterfaceorientation)tointerfaceorientation duration:(nstimeinterval)duration
{
 //纵屏
 if (uiinterfaceorientationisportrait(tointerfaceorientation)) {
 cgrect frame = self.functionview.frame;
 frame.size.height = 216;
 self.functionview.frame = frame;
 self.moreview.frame = frame;
 
 }
 //横屏
 if (uiinterfaceorientationislandscape(tointerfaceorientation)) {
 cgrect frame = self.functionview.frame;
 frame.size.height = 150;
 self.functionview.frame = frame;
 self.moreview.frame = frame;
 }
}

4.当键盘出来的时候,改变toolview的位置,通过键盘的通知来实现。当横屏的时候键盘的坐标系和我们当前的frame的坐标系不一样所以当横屏时得做一坐标系的转换,代码如下:

?
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
//当键盘出来的时候改变toolview的位置(接到键盘出来的通知要做的方法)
-(void) keynotification : (nsnotification *) notification
{
 nslog(@"%@", notification.userinfo);
 
 self.keyboarddic = notification.userinfo;
 //获取键盘移动后的坐标点的坐标点
 cgrect rect = [self.keyboarddic[@"uikeyboardframeenduserinfokey"] cgrectvalue];
 
 //把键盘的坐标系改成当前我们window的坐标系
 cgrect r1 = [self.view convertrect:rect fromview:self.view.window];
 
 [uiview animatewithduration:[self.keyboarddic[uikeyboardanimationdurationuserinfokey] floatvalue] animations:^{
 
 //动画曲线
 [uiview setanimationcurve:[self.keyboarddic[uikeyboardanimationcurveuserinfokey] doublevalue]];
 
 cgrect frame = self.toolview.frame;
 
 frame.origin.y = r1.origin.y - frame.size.height;
 
 //根据键盘的高度来改变toolview的高度
 self.toolview.frame = frame;
 }];
}

5.系统键盘和自定义键盘切换的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//切换键盘的方法
-(void) changekeyboardtofunction
{
 if ([self.mytextview.inputview isequal:self.functionview])
 {
 self.mytextview.inputview = nil;
 [self.mytextview reloadinputviews];
 }
 else
 {
 self.mytextview.inputview = self.functionview;
 [self.mytextview reloadinputviews];
 }
 
 if (![self.mytextview isfirstresponder])
 {
 [self.mytextview becomefirstresponder];
 }
}

以上就是上面展示效果的核心代码了,在做的时候感觉难点在于如何进行屏幕适配,尤其是当屏幕横过来的时候键盘的坐标系和我们frame的坐标系不同,得做 一个转换。发表文章的目的是想起到抛砖引玉的左右,有好的东西希望大家相互交流一下。

延伸 · 阅读

精彩推荐
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01