Matrix 是少数派的全新产品,一个纯净、小众的写作平台,我们主张分享真实的产品体验,有实用价值的互联网领域经验、思考。欢迎忠于写作,喜好分享的朋友参与内测。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。
本文内容仅代表作者本人观点,文章对标题和排版略作修改,原文链接。
编辑说我前面写的那篇《拼音原来可以这么玩!》偏软文风格,手起刀落就给删了……其实我只是文风比较活泼跳脱而已啦……好吧,确实有点软。由此可以看出,少数派对文章的质量要求还是很高的。那么,请允许我重新讲述这个关于岁寒输入法的故事吧。
我与岁寒
首先,先隆重介绍一下我自己,我叫岁寒,而我要向你介绍的这款输入法叫岁寒输入法,没错,你猜得没错,我正是岁寒输入法的作者。这里之所以用的「临岁之寒」的笔名,是因为我最开始用微信登陆少数派时用的就是「岁寒」这个昵称,而申请到 Matrix 内测资格的却是我的邮箱,也就是说,我自己把自己的笔名给占用了……好尴尬呀。
「岁寒」一词的出自论语:子曰,岁寒,然后知松柏之后凋也。不过后来,我发现了更时髦的解读——「岁寒」与《冰与火之歌》中临冬城史塔克家族的家训「Winter is coming」有异曲同工之妙。
开发动机
大多数时候,一个人做一件事情,是有其动机的,就像杀人总得有杀人动机是一个道理。开发一款应用,特别是开发一款前途无望的应用时,动机就变得令人好奇。其实我就是想在手机上写写东西而已。你看我文风如此清奇,想必可以看出我是「练过的」,曾经我的梦想是成为一名小说家(现在也还是)。我当时尝试了一些手机输入法,体验都不能令我满意,输入繁复,效率也一般,于是我萌生了开发一个自己的输入法的想法。
这是我最开始的动机,十分简单,甚至有些中二。但动机这个东西是会变化的,起初只是想尝试尝试,后来是想用它来证明自我,再后来它变成了一种坚持,变成了一份事业。
滑行为王
那是 iPhone 横空出世,Android 开始当道的时代,触摸屏的出现使手机的可操控性上了一个台阶,但是大多数手机仍然沿用旧有的点击式输入,在我看来,这是一种极大的浪费。当时 Swype 滑行输入法已经问世,但还不适合于中文输入,却给我带来了许多启发。从那之后,利用手机的滑行特性来提高输入的效率和趣味便成为了岁寒的核心理念,而这一理念,至今不变。
但最开始时,我所构想的输入法并不是现在这种拼音输入方案,而基于五笔的改进型,做了岁寒输入法 v1.0 和岁寒输入法 v2.0,不过尝试的结果都以失败告终。从中,我得到的教训是,五笔此路不通。当然了,我想在失败的原因中,有一部分原因是我的输入法界面做得太丑陋了,嗯……可能有一半吧,嗯……也可能是大部分吧,嗯……也可能是全部。(左边是岁寒输入法 v1.0,右边是岁寒输入法 v2.0)
于是我放弃了在五笔方案上的尝试,而开始思考更为大众所熟悉的拼音输入方案有没有可能与我的滑行理念取得融合。
放眼当时江湖,拼音滑行输入法已经呼之欲出,像搜狗、百度、Google 这些大厂嗅觉之灵敏不必分说,自然能够意识到滑行输入对用户的吸引力有多大。不过他们大都因循守旧,只在旧有的 qwerty 布局上作锦绣文章,利用其技术上的优势,使用数学分析的方法提取用户滑行中的特征,从中获得用户的真实输入意图。而这种做法存在天然的缺陷,那就是滑行距离太长,因此效率甚至还不如点击式的全拼输入法。
与此同时也有敢于打破桎梏的,先行者有 AEVIOU 蜂窝式中文滑行输入法、闪云滑行输入法(但真的一点也不好用)还有盛大也凑热闹地做了一个盛大输入法。难能可贵的是,他们都敢于在 qwerty 键盘上做些微调来适应滑行输入的需要。但问题在于,他们并没有走对方向——他们无一例外都选择了动态布局的滑行方案。
所谓动态布局,就是在用户按下第一个字母后,据此在触点中心(或在周边)浮现一个新的键盘,以让用户可以方便的滑行到想要的键位上。可能我的描述有失精准,但做法上大体如此。方便用户滑行这个用意自然是很好,但同样存在一个天然的缺陷,即每一个键位可能对应一个完全不同的新键盘,如果用户想快速输入怎么办呢?好像只有把所有的变化都背下来吧。所以,这种做法在效率上也有问题,正确的方向应该是静态布局。
方案上的缺陷可以通过技术上的进步来弥补,但不可能予以真正的解决。想要彻底解决,就要对方案进行重新设计。这意味着要彻底打破 qwerty 布局对我们思维的限制,去构想一个适合于汉语拼音滑行的新布局,而不是改一点留一片。既然不适合,就应该推翻掉重来,要相信「不破不立」。
于是,我站在一片荒地上开始我的耕作。
布局之道
想要在静态布局上实现高效的拼音滑行,一定要结合拼音的结构特点才行。经过研究,我发现,汉语拼音在结构上非常有特点,这里我指的是数学上的排列组合,而不是音韵学上的平上去入。说了你可能不信,我一个做拼音输入法的人对音韵学几乎一窍不通。
汉语拼音方案是利用英文已有的 26 个字母转化而来,在此我们应该感谢已逝的周有光先生,感谢他的天才创造。这里,我把 a、o、e、i、u、v(习惯上,我们用 v 来替代 ü)称为韵母字母,除此之外的字母称为声母字母,那么拼音在结构上,存在这样的两条重要的规律:
除了 zh、ch、sh,其它声母就只有一个字母,而 zh、ch、sh 都以「h」为后缀;
在韵母中只存在3个声母字母:n、g、r,其中 r 只有「er」一种情况,声母字母总是缀在韵母字母之后,而且当 n 与 g 同时存在时,n 总是在 g 之前。
把「er」算为特例的话,在声母和韵母中则大量的存在 3 种后缀结构:h、n、g。
如果按照习惯的做法,一定要按顺序滑过相应的键位才能输入相应字母的话,我们在一个平面上是不可能使所有其它韵母都能够以最短的距离靠近这 3 个字母所对应的键位的,必然会导致远近不一的情况。
我问自己,「按顺序滑过相应的键位才能输入相应字母」是否是必要的?比如我想输入sh,我是不是一定要从「s」滑到「h」上不可?
此时,我想起了高中化学里面「族」这个概念,元素周期表中的每一竖列都是一个族,在同一个族中的元素在化学性质上会有相似之处。受此启发,我想到,如果有一群键位在滑行时都表现得像「h」,那输入 zh、ch、sh 时就近滑行不就可以了吗?n 和 g 的情况也是类似的。那么多少键位适合做这一群键位呢?我想,一行应该是一个不错的单位。我效仿化学的概念,称它们为「h 族」、「n 族」和「g 族」。
巧合的是,拼音中最长的韵母不过 4 个字母,因此岁寒输入法的键盘有 4 行,除去第一行,正好剩下 3 行可用,于是他们就与 3 个键族一一对应起来了。
接着,我对韵母字母的位置作了一番研究后,发现 u、i、v 出现在 a、o、e 之前的情况更多一些,因此 u、i、v 放置在 a、o、e 之上。但这带来了另一个问题,u、i 离 n 族有一行的距离,想要输入 in、ing 和 un 的话比较麻烦。为了解决这个问题,我引入了声韵混合键——在第二行找两个声母作为滑行时 u 和 i 的替代,即在点击时它们还是自身,但是当从它们上滑出时,它们就代表 u 或 i 了。于是,我得出了下面这样一个布局。
再配合下列输入规则,
- 单个的声母或韵母直接点击获得;
- 带 h 的声母从首字母滑到第二行;
- 带 n 的韵母从首字母滑到第三行;
- 带 ng 的韵母从首字母滑到第四行;
- 利用 y,r 这两个声韵混合键可以快速的输入 un,in,ing;
- 其它的韵母依照字母顺序滑过即可;
从而在一个静态布局上实现了「任何一个声母或韵母都可以在一个操作之内完成」的目标。可以看到,岁寒输入法并不是只有滑行,而是将点击和滑行两种操作结合起来,各取所长。谁说滑行输入法就一定只有滑行操作?在只有一个字母的情况下,滑行输入就有点脱裤子放屁的意味了。
在此,岁寒输入法实际上是借鉴了双拼输入法的核心思想,即将拼音分为声母和韵母,并将其作为基本的输入单位,而非全拼那样以字母为输入单位。所以,从一开始,我就对外宣称,岁寒输入法是「双拼变种」。说了也许你不信,我一个做双拼变种输入法的至今仍没有掌握任何一款双拼输入法的具体用法。
而大多数滑行输入法都喜欢在一次滑行之内就输入一个拼音,你可能会说,这样效率不是也更高吗?在部分情况下确实如此,但将声母和韵母分开输入并非多此一举,恰恰相反,这个做法为岁寒输入法带来了极大的输入灵活性,也塑造了岁寒输入法许多与众不同的特性。
无二义性
在设计完岁寒输入法的布局和输入规则后,我惊奇地发现岁寒输入法呈现出一种非常重要的特性——输入声韵的无二义性。简单地说,就是任何一条滑行路径都明确地指向某一个声母或者韵母,不会存在歧义。
这有什么可惊奇呢?要知道,这个特性是其它许多拼音输入法都不具备的。还是以全拼和双拼为例。
在全拼中,如果没有分音键的话,平常输入的许多拼音都是有歧义的,比如「xian」也可能是「xi'an」,那「gang」也可能是「gan'g」,这些情况其实非常普遍。之所以平时我们感觉不出来,是因为现在的输入法都会很聪明地将两种可能的结果都呈现给我们,或者预测当下我们意图输入的是什么。这就是我所指的,通过技术的进步来弥补方案的缺陷。
而在双拼中稍微好一些,因为引入了零声母为作为无声母情况的占位,从而实现在拼音层面上的无二义性。但是既然双拼每一次输入的都是一个声母或一个韵母,这个时候如果我们仔细去看,双拼在声母或韵母的输入是否有无二义性时,就会发现它没有,也不可能有。按照双拼的分法,汉语拼音可分为 23 个声母和 33 个韵母,而 23 + 33 > 26 * 2。简单的数学计算可知,键位不够表示这么多声韵,就算是番了一翻还是不够,所以有些韵母势必要挤在一起共用一个键位,出现「二女共侍一夫」的情况。不过双拼方案还是很聪明地解决了这一问题,因为不是任意的声母和韵母都可以组合成合法拼音,利用这一点,可以在已知声母的情况下,确定用户输入的韵母到底是哪一个。但这也意味着,韵母的确定依赖于已输入的声母。
而在岁寒输入法中,输入本身是自解释的,任何一次输入都可以明确地知道这次输入是声母还是韵母,是声母是哪个声母,是韵母又是哪个韵母,不依赖于已经输入的信息,也不依赖于还没有输入的信息。
无二义性这个性质非常之重要,岁寒输入法几乎所有与众不同的特性都是以此为基础。
自然生长
万物有灵,生命的开始只需一颗种子和阳光雨露,就会自然生长。
岁寒输入法对于我而言,就是这样一个小生命,他后来的许多特性都不在我最初的设计预想之中。正像是在撰写一部玄幻小说,小说的设定究竟可以如何组合演化,作者可能在动笔时并没有完全想好,只是觉得这个设定很酷,而当剧情逐步演进,那些设定才会显露出它们神奇的一面,也许会极大地出乎作者的意料。
当我去思考如何处理无声母的拼音的情况时,我发现,既然岁寒输入法有无二义性,那完全不需要任何多余的操作,直接输入韵母即可。于是我又想,为什么其它拼音输入法中韵母如此依赖于声母,像在全拼中,韵母可以省略,而声母是不可以省略的,韵母的地位为何会如此不堪呢?这很大程度上,是由于汉语拼音中存在无声母的情况。因为总是有的东西没有了,那肯定是省略了,而有可能有也有可能没有的东西如果没有,那就不好说是没有了,还是省略了。那么如果我假设所有拼音都有声母会怎样?于是我提出了一个概念——虚声母,一个假设存在又从来用不着的声母。既然所有拼音都有声母,那么在输入时省略声母就不是什么奇怪的事情了。
需要指出的是,岁寒输入法的虚声母跟双拼输入法的零声母是完全不同的,零声母是「以有为无」,而虚声母是「以无为有」。
虚声母可不是纯粹为了炫技而提出的,且不说虚声母丰富了拼音输入的组合形式,配合岁寒输入法的特征码机制可以有较地降低重码率,就说如果没有虚声母,声韵匹配机制就无从谈起。
前面提到过,并不是任意的声母和韵母都可以组合成合法的拼音,比如说「gi」这个拼音就是无效的。那如果出现这种情况,我应该怎么办呢?是应该直接认为用户输入错误忽略之,还是应该接受这个输入但在候选区显示一片空白,好让用户知道自己输入错误了呢?此时,我退了一步想,为什么出现这种情况时一定要认为是用户输入错误呢?说不定这正是用户的意图呢?有没有可能他是想输入第一个字的声母和第二个字的韵母,不过刚好两个不匹配而已?于是我设计了声韵匹配机制,来帮用户自动完成了这个操作。
这个特性可以利用来减少输入的次数,比如我就经常输入「f'er」来获得「反而」,屡试不爽。而这一切必须在引入虚声母之后才可以,因为第二个字省略了声母。
而在加入声韵匹配之后,岁寒输入法立刻获得了另一种特性——输入无错性。
这种无错性表现在:
- 用户无法输入不正确的声母或韵母;
- 用户输入不匹配的声母和韵母时,会被拆成两个拼音;
- 省略声母也是正确的。
因此岁寒输入法不存在形式上输入错误的情况。
独特功能
除了上述的特性之外,岁寒输入法还有许多独特的功能。这些功能有的依赖于岁寒的特性,有的是为了解决某些场景下存在的问题,也有的解决了输入法使用中普遍存在的疼点。
拼音替入
虽然岁寒输入法不存在形式上的输入错误问题,但由于用户操作失误,而输入与其输入意图不符合的情况却是不可避免的。应对这种情况,岁寒输入法提供了一样强大而简单的功能——拼音替入。
因为岁寒可以在一次操作内输入任何一个声母或韵母,再加上其输入无二义性,也不依赖于其它已有的信息,所以替换掉任意位置的某个声母或韵母是一件轻而易举的事情。这无论是对于全拼,还是双拼都是难以做到的,因为即使勉强做到了,其操作势必也无法做到简洁明了。而在岁寒输入法中,想要替换或插入一个声母或韵母,操作仅仅是:选中想要操作的拼音,直接输入正确的声母或韵母即可。这个操作简洁到没有一丝冗余,自然而强大。
截取优先
岁寒输入法拥有手动造词功能,造词的方法是先输入词组的拼音,然后将词组中的子词组点击上屏之后就自动完成造词。根据用户的反馈,造词功能在实际使用中存在这样一个问题:岁寒输入法是以特征码、等长度匹配、超长度匹配、不等长度匹配的顺序显示候选词的,那么在所要造的词组中涉及选字时就会特别麻烦,因为输入的拼音越长,字的候选位置就会越靠后。
为了解决这一问题,我加入了截取优先功能,用户可以选择某个位置的拼音,命令输入法以该位置之前的拼音作为优先检索的条件。
词组回退
词组回退功能不依赖于岁寒输入法的任何特性,它要解决的是日常输入中的一个疼点,就是在输入拼音完全正确的情况,用户有可能手抖选错了候选词,好尴尬的!我们要删除掉已经上屏的词组,然后还要重新再输入一遍拼音,才能选择正确的候选词。问题是,有必要这么麻烦吗?删掉已经上屏的词组,和再输入一遍拼音这个工作为什么不交给输入法去做呢?
用户只需要从 enter 键上向左滑出,一切就回到点击候选词之前的状态。虽说「落子无悔大丈夫」,但这种时候就不要那么较真了嘛。
上述三个功能,是我拣选岁寒输入法中比较的代表性的功能,毕竟这不是使用说明书,没有必要一一讲解。其实岁寒输入法还有其它一些功能,比如为了方便选字而加入的笔划筛选功能,还有在用户强烈要求下逐步探索后加入的连滑机制。
这个连滑机制最开始只是独韵连滑,即只能和仅有一个字母的韵母进行连滑,后面放开了这一限制。但连滑机制并不是完美的——连滑机制只适用于方便某些拼音的输入,并不能适用于全部拼音,这也是我没有将它拿出来着重讲解的原因。
岁寒输入法也有很多不足之处,比如界面不够美观、词库不够强大、智能整句功能也不够强大(Android 版已有,iOS 还没有)等等。但我想说的是,这些都是技术上的不足,技术上的进步可以弥补方案的缺陷,而技术上的不足却不能够掩盖方案的光芒。有些技术上的难题,以个人之力确实难以克服,所以如果有认识像马云、马化腾、雷军、罗永浩这样的人物的朋友,麻烦帮助引荐引荐,在此提前谢过。
如果你想了解更多关于岁寒输入法的信息,可以查看 岁寒输入法 iOS 版使用教程;如果你想下载岁寒输入法的话,Android 用户请前往 酷安的岁寒输入法页面,iPhone 用户请前往App Store 搜索「岁寒输入法」,这里需要说明一下,Android 岁寒输入法是免费的,而 iOS 岁寒输入法是付费的,售价为 3 元人民币。
写在最后
岁寒输入法于我已经不是一款应用那么简单了,他更像是我的孩子。最开始他蹒跚学步,跌跌撞撞,如今已能微微站定,他想朝大家挥手,想得到这个世界投射过来的目光。如要问岁寒今年几岁?我想,大概是有 6 岁了吧。
原文可获取应用下载链接:我是如何开发岁寒输入法的:滑行输入的探索之路丨Matrix 精选
喜欢少数派?欢迎关注我们的微博:@少数派sspai ,微信公众号: sspaime
少数派( http://sspai.com )