iOS表情符号是一项严肃的业务-第2部分:模仿iOS 8.3的表情符号键盘

如上一章所述,由于表情符号及其各自类别的数量不断增加,Apple重做了表情符号键盘。 任何运行iOS 8.2及更低版本的设备都必须进行一些转换(使这些固件中的键盘类似于新设计)。

较早的版本(iOS 8.2和更低版本),表情符号键盘的实现位于UIKeyboardEmojiScrollView类中,该类继承自UIKeyboardEmojiScrollView类(不是UIScrollView但扩展了UIScrollViewDelegate )。 表情符号类别栏(类别选择视图,或者您可以调用)通过UIKeyboardEmojiCategoryBar类实现。 UIKeyboardEmojiScrollView包含许多UIKeyboardEmojiPage页面,通过在类别栏上点击相应的图标或类别可以显示每个页面。 为了便于理解,在上图中,“人物”类别有九个UIKeyboardEmojiPage页面。

苹果公司决定在iOS 8.3的发布中使用一种更合适的具有自动布局功能的类来列出表情符号。 子类化为UIKeyboardEmojiCollectionView 。 虽然,它是UIKeyboardEmojiCollectionInputView的子视图,当然, UIKBKeyView具有超类。 挑战在于,如何将这种设计模仿到iOS 8.3之前的版本。

复杂的部分是如何在iOS 8.3之前的版本中放置每个表情符号图像。 如果我们更改行数或列数,则图像将不会动态定位。 为了说明,让我们从UIKeyboardEmojiGraphics的布局逻辑开始。

  @interface UIKeyboardEmojiGraphics:NSObject 
+(instancetype)sharedInstance;
+(CGFloat)emojiPageControlYOffset:(BOOL)人像; // iOS 7以上版本
+(CGSize)emojiSize:(BOOL)人像;
+(CGPoint)保证金:(BOOL)人像;
+(CGPoint)填充:(BOOL)人像;
+(NSInteger)rowCount:(BOOL)人像;
+(NSInteger)colCount:(BOOL)人像;
@结束

这意味着您可以控制表情符号图像的大小,行数和列数,边距应多大以及每个连续表情符号之间的间隔(填充)。 这些值是常数,但是我们的目标是例如将表情符号数组从3 x 7(在iOS 8.3之前)转换为5 x 8(iOS 8.3、3.5英寸和4英寸iPhone)。 iPhone 6 Plus的屏幕尺寸为5 x 9,iPad屏幕的尺寸为3 x 12(纵向)。 必须为这些动态数字调整填充。

我们可以将所有内容放到方程式中。 令k代表键盘(例如k_w是键盘宽度), m代表边距, c代表每行表情符号数量, r代表每列表情符号数量, o代表从顶部开始的y偏移量, e代表单个表情符号图像。 我们有:

我们可以找到正确的填充,如下所示:

m_b表示表情符号页面底部的边距或空白。 此值是必需的,因为在页面顶部和底部都使用其他边距会使表情符号矩阵偏离中心。 现在,查看结果:

现在看起来更像是现代设计,同时保持了以前的配色方案。 还有其他修改,例如添加在底部栏中看到的其他表情符号类别图像,以及在左上角看到的每个类别的标签(例如,食品和饮料)(替换灰色点)。 这两个都不再讨论。 修复或转换不是很困难。

因为这种新设计使键盘更高,所以我的工作是在所有可能的iPhone和iPad上获得键盘高度的确切值。 事实证明,可以在iOS上显示的所有可能类型的键盘都有很多预定义的键盘布局。 每个布局不仅定义键盘的大小,而且还定义诸如包括哪些键,每个键的大小以及在长按目标键时弹出的其他键之类的内容。 这次我们使用Hopper Disassembler浏览代码并获得理解。 这是/System/Library/PrivateFrameworks/TextInput.framework/TextInput一个相关函数:

每种设备类型上的每个键盘都有自己的代号。 给定屏幕宽度,此功能确定整个系统应使用的键盘布局。 我们可以看到iPad(1024×768)使用Wildcat 。 更有趣的是,不同尺寸的iPhone具有不同的代号。 Choco适用于iPhone 6, 松露适用于iPhone 6 Plus,那些名字不奇怪的产品则用于4英寸设备,如iPhone 5和iPhone 5s。

实际布局在上面的二进制文件所在的目录中的KBLayouts_iPhone.dylibKBLayouts_iPad.dylib中进行了硬编码。 但是,由于苹果使用了一个不可预测的像哈希一样的数字作为函数的前缀,因此无法从那里进行更改,也许是因为此dylib太大,以至于我尝试将其加载到测试设备后,它就崩溃了。为了挂钩功能。 幸运的是,我们可以选择挂钩依赖于这些不可预测功能且更安全处理的代码。

还有一件事。 如果仔细观察,iOS 8.3之前版本的键盘上的表情符号主要是行,而现代键盘设计使用主要是列。 消除这种差异的最简单方法是使用以下算法来操纵将为iOS 8.3之前的键盘绘制的表情符号的顺序:

 对于i在范围(0,r)中 
对于范围(0,c)中的j
k =(j * r)+ i
如果(k <n)addEmoji()// n = r * c
否则addBlankSpace()

可以在这里找到表达本文(以更高级的方式)的真实代码。

还有更多。 头脑已经吹了吗? 🤯