表情键盘

表情键盘

添加表情键盘

当点击表情按钮的时候, 切换成自定义键盘, 可以先用一个 View 来测试, 需要使用输入框的 inputView, 才能让他自动相应输入框的点击时间, 切换输入框,就可以切换到自定义的 view, 在改变 inputView 的时候, 是没有立即反应的,要重新成为第一响应者的时候才会看到效果, 先登出,在注入第一响应者.
点击时改变按钮的图标, 可以在监听点击事件时, 判断是表情按钮, 就将表情按钮的图片改变. 或者提供一个方法,显示 emotionImage,内部将图片更换,
当点击切换的时候, 不应该让工具条下去, 而是保持: 可以设置一个是否切换的 BOOL, 监听 hideKeyboard 的时候判断这个 BOOL. 是切换状态的话就不做反应
添加表情键盘的时候, 分为两部分, 上半部是表情列表, 下面是工具条(可以直接写在 emotionView 里, 用 view 封装在一个就行, 不用在弄个类,)
设置工具栏按钮的时候, 抽取出方法来, 因为每个按钮的文字都不同, 在添加方法里判断当前添加的是第几个: 看toolBar 里的按钮有几个,添加进去后肯定是最后一个, 所以个数即是它的第几个.新浪根据按钮的位置有不一样的图片, 所以这里要判断,

表情键盘的建立 TT2016.06.25 ~~

给自定义键盘传入 emotion 模型后, 计算出有多少页, 根据模型设定指示器数量, 创建 scrollView 的子 View,数量岁模型,
注意这里是在没词传入 emotions 的时候, 都会为 scrollView 创建子 VIew 添加到上面, 这样会累加, 应该每次添加前先清掉之前的 .
再首次创建 scrollView 的时候才会调用 layoutSubViews,所以在点击切换表情的时候,子 view 是没有 frame 的, 没词创建好后要带哦用 setNeedLayout
每个子 view 都有很多内容和操作, 且都应该自己管理好里面的控件, 应该单独封装起来,
注意, 在最后一页可能会有不够每页的数量,直接取 range 的话会发生数组越界...需要对越界进行判断处理,
每个表情的按钮用 button, 因为 emoji 表情是字符,在系统里转码显示的.每个button应该仅仅挨着,图片直接设置 Image 居中,这样在滑动选择的时候就能一过就是另一个
在用 NSBundle 来获取内容时资源可以是带路径的资源(用与在 bunble 里存在的文件夹里的文件)...图片的话直接 Imagename 传入带文件路径的 string+name.png`也可以拿到 bundle 中文件夹中的资源....
运用数组的 makeObjectPerform...可以让所有数组元素调用某一个方法.设定好文件夹属性后, 就能从 BUndle 里获取资源了,
在点击不同的标签时, 应该让 page 回到第一页:在每次点击时, 设定为第0页, 滚到最开始,
显示 emoji: emoji 在内存中是以十六进制存储, 要把它转为 unicode 字符,可以用一个别人写的分来来转换
emoji 的大小取决于字体大小, 值相当于图片的宽高

生成随机数: arc4Random()

性能优化

* 在表情键盘中每次都要销毁和创建 scrollView 的子控件 gridView 很耗性能, 我们应该对差不多的东西重复利用,
* 在 gridView 中, 每个其子控件 button 也没必要重复创建, 或者,当 gridView 重用后,里面的 button 还在, 不做覆盖处理的话没词传入 emotion 模型又会创建 button 添加到上面, 最后的结果就是刚添加的 Button 被排到很后面, 而滚不过去, 我们也应该对 Button 进行覆盖重用
* 可以用这个思路, 需要的 view 和拥有的 view 哪个多就遍历哪个数量, 当遍历到多过拥有的时->创建, 不然就取出重用(当超过需要的时->隐藏并 continue), 最后拿到的 view 都要取消隐藏
* 每个 button 对模型还做了一些处理, 之后可能还会做跟多处理, 应该把其单独抽出来作为一个类

封装 emotionView

将 Button 封装起来, 传入模型, 在里面判断就可以了

挖掘子控件,

有时候为了调试, 我们可以将整个 window 的 subVIew 打印出来, 看下层级关系, 在遍历的时候将子控件的关键信息拼接成字符串给 xml, 在浏览器中打开就可以清楚的看到层级关系

单击表情按钮弹出提示 View

监听按钮点击, 用 gridView 监听, 因为还要用到一个 popView 的东西, 没必要重用,
将点击按钮整个传入, 就能知道按钮的内容和位置
创建一个 popView 将点击的按钮显示出来, 里面要有一个 emotionCell 来展示点击的按钮
在设置按钮的时候 去掉动画, 设置完后拿回动画

长按表情

添加手势监听长按
判断当前点是否在 emotionCell 的范围, 拿到判断返回的 emotonCell
没抬起手时, 结果传给popView,  nil 就不做操作, 不然显示出来,
当收抬起时, 发送通知, nil 的话不做操作,
点击删除按钮也发送通知
在发微博控制器监听通知进行操作

最近表情

当点击表情能发送通知时才是确实发了表情, 这里应该放到最近表情中保存一份
    可以使用单例类, 使数据在内存中只有一份, 这个类可以做一个管理者
    也可以使用工具类, 创建几个 static 全局属性, 也可以保证全局中只有一份. 这种做法好像比较方便
最近表情可以从沙盒中获取这个最近表情数组, 通过 NSCoding 将 emotion 模型保存起来, 之后拿来调用放到 emotionCell 中
记得保存自定义对象时还要用 NSKeyedArchive 类
???? 解码过程中碰到有的关键字是没有对应到的

bug: 在重新打开应用后表情键盘添加到最近不能判断出原来已经有了,

---- 添加的时候判断手否存在时是靠传入对象的-isEqual 方法, 逐个传入自己数组中的每个元素进行内存地址判断,一样的就返回 yes, 但是重新打开后是不一样的地址.
重写-(BOOL)isequal:方法, 其中判断改为判断 png 或者 code

bug: 在没有键盘时点击表情按钮键盘出来, 再拖拽文本框键盘下去,但是 toolBar 没有跟着下去

--- 在按钮点击那一刻 isChanging = yes -> 退出第一相应者 -> 因为还没有键盘不会发 hide 通知 -> changing=No 不能调用, -> 代码过不到收回 toolbar 那里,
    ---- 应该把 changing = NO 卸载退出第一响应者后, 不管能不能收起键盘, 操作完成后都回复 changing 状态

小问题, 实时刷新的话, popView 还在显示本来 emotionView 时那个就跳到前面去了, 应该等 popView 消失时在刷新