出处:
本来不想写的时候要根据不同手机平台适配各种键值这个问题,觉得没撒意思,也没什么技术含量,但是今天看到了一个让我很无语的东西,所以我决定要写出来。稍候再说这个让我不爽的东西,先不要影响我们分享技术的心情。NOW BEGIN …
故事背景:最近要开发一个世界天气在线搜索的软件,先AD一下,这个软件是我们开发的有一个生活小软件,开始的定位就是天气搜索,后来我想扩展为“生活小助手”就是不但有世界天气搜索,还有出行参考,还有生活常识之类的东西。正在开发中。 由于,开发过程中需要使用才能做出很漂亮的界面,所以引发了一个老问题 — 手机键值!
很多人都说,要适配所有值是不可能的。因为,已是J2ME中没有对手机的左右软键的键值定义,而是很多手机也没定义,再者就是手机多多了,像华为,中兴,联想,诺基亚,摩托罗拉,西门子,索爱,黑莓,多普达等等这些大厂家都没个定数,更别所多如牛毛的山寨机了,所以这种说法也是无可厚非的。 即使你把 左键 -7 , 右键 -6 , OK键 -5 这些都设置好能支持大部分的手机,还是难免有个害群之马啊。 所以, 没有标准导致了这个严重的问题 :要一次性搞定所有手机的键值问题难道非常之大。
但是,天知道我怎么一生下来就是个不信邪的主儿,Google百度了几下发现没有统一键值之后开始思考自己的路了。{zh1},想了一个办法,目的是我要一次性搞定所有手机的键值。怎么做?让用户手机告诉你呗。思路如下:用户{dy}次使用时设置键位。
- 用Canvas实现一个键位设置界面,捕获keyPressed事件;
- 在设置界面中以提示性语言引导用户按键;
- 将得到的保存到中备用;
- 完成键位设置;
- 在以后要使用按键的中调用RMS中的数据,完成操作。
下面是完成这个设置的简要代码结构:
- //首先你需要一个数组:
- private?String[] drawArray = {"左功能键","右功能键","OK键","方向键【上】","方向键【下】","方向键【左】","方向键【右】"} ;
- //然后你需要两个标志位
- private?boolean config_finished = false ;
- private?boolean firsttime = true ;
- //再者你需要一点实现逻辑
- if(drawIndex > 6){
- ? ? config_finished = true ;
- ? ? ? ? }
- ? ? if(!config_finished){
- ? ? if(firsttime){
- ? ? g.drawString("【键位设置】",WIDTH / 2 - titleWidht / 2 , startY, Graphics.TOP|Graphics.LEFT);
- ? ? g.drawString(initStr, 5, startY + 1*lineHeight, Graphics.TOP|Graphics.LEFT);
- ? ? g.drawString(prefix + drawArray[drawIndex] , 5, startY + 2*lineHeight, Graphics.TOP|Graphics.LEFT);
- ? ? }?else {
- ? ? g.drawString("【键位设置】",WIDTH / 2 - titleWidht / 2 , startY, Graphics.TOP|Graphics.LEFT);
- ? ? g.drawString(initStr, 5, startY + 1*lineHeight, Graphics.TOP|Graphics.LEFT);
- ? ? g.drawString(finished + drawArray[drawIndex - 1] + status, 5, startY + 1*lineHeight, Graphics.TOP|Graphics.LEFT);
- ? ? g.drawString(prefix + drawArray[drawIndex] , 5, startY + 2*lineHeight, Graphics.TOP|Graphics.LEFT);
- ? ? }
- ? ? firsttime = false ;
- ? ? startY = 0 ;? ?
- ? ? initStr = "" ;
- ? ? }?else {
- ? ? System.out.println("设置完毕 .... config finished ...");
- ? ? g.setColor(0xff0000);
- ? ? g.drawString("设置成功,请按OK键返回!", 5, startY + 4*lineHeight, Graphics.TOP|Graphics.LEFT);
- ? ? }
- //接下来我们需要一点控制信心和按键事件的响应
- ? ? protected?void keyPressed(int key){
- ? ? ? ? if(this.storeKeyValue(WHAT_KEY, key)){
- ? ? ? ? ? ? drawIndex ++ ;
- ? ? ? ? ? ? WHAT_KEY ++ ;
- ? ? ? ? ? ? status = "(成功)" ;
- ? ? ? ? }?else {
- ? ? ? ? ? ? drawIndex -- ;
- ? ? ? ? ? ? WHAT_KEY -- ;
- ? ? ? ? ? ? prefix = "[重设]" ;
- ? ? ? ? ? ? status = "(失败)" ;
- ? ? ? ? }
- ? ? ? ? if(config_finished && key == config.getOK()){
- ? ? ? ? ? ? System.out.println("read back of OK .. is " + config.getOK());
- ? ? ? ? ? ? wm.setThisAsCurrent(wm.getMainform());
- ? ? ? ? }
- ? ? ? ? repaint();
- ? ? }
- //{zh1}我们需要一个存储的动作
- ? ? private?boolean storeKeyValue(int whatkey , int key){}
请注意,上面这个代码片段只是完成按钮设置的框架,而不是完整代码,如果你需要完整代码可以留下信息并且发邮件告诉我。我会分享给你的。
下面说一下上面这段代码的大致思路:
创建一个你希望设置的键位的数组:private String[] drawArray , 里面存放着一些提示信息,这些信息用来引导用户去按键,然后使用在界面上绘制这些信息,但又按键事件的时候系统会调用protected void keyPressed(int key)方法,而我们在这个方法中处理一些事件,不作一些控制。例如改变绘制字符串的指针,例如修改的执行状态 “成功” 或者 “失败” 。 另外还需要控制的就是设置的完成状态 , 最终目的是把键值写入到RMS中备用 。
下面是键值调用的持久类的完整代码:
- package org.allove.weather.lib;
- public?class KeyMap {
- ? ? ///////////////
- ? ? private?static KeyValueRms config = KeyValueRms.getInstance();
- ? ? public?static final int key_LeftSoft = config.getLeftSoft() ;
- ? ? public?static final int key_RightSoft = config.getRightSoft() ;
- ? ? public?static final int key_OK = config.getOK() ;
- ? ? public?static final int key_UP = config.getUP() ;
- ? ? public?static final int key_DOWN = config.getDown() ;
- ? ? public?static final int key_LEFT = config.getLeft() ;
- ? ? public?static final int key_RIGHT = config.getRight() ;
- ? ? ///////////////
- }
至于这个KeyValueRms 怎么去实现就不是本文的主要内容了,这是的内容,这里就不赘述了 。
总的来说,我觉得这是一个很简单的问题,也很容易想到,应该不到5分钟吧,想到这个解决方案。由于我觉得这个东西很简单,价值也不那么明显,所以导致了我看到一个东西之后很郁闷。今天,无意中搜索键值玩,发现了万方数据里面的一片论文:《》让我倍感无语。这个方法被人申请专利了,我很无语,这东西也能申请壮丽,我操,早知道我早两年也去申请了。 还说得那么玄乎,很纠结啊。
{zh1},要来说一下这个可行性和用户体验的问题。
- 其实这东西不是很好,xx依赖于keyPressed方法,如果不支持这个方法呢?
- 在某些手机中按左右软键的时候是没有反应的,比如巨头诺基亚
- 再说用户体验,这个问题有点严重,一旦设置错误可能就需要从新安装软件,这是相当不友好的,因为RMS的数据要卸载才能xx,其实这个到也无所谓啦,你可以在软件里面做一个重新设置的功能,这到不致命
- 然后就是,不是所有用户都能看懂你的引导语言,难免会设置错误,你不能保证每个用户都是聪明的
- 由于手机厂商数目巨大,这个方法的代价是巨大的,慎用
抛弃这种方法之后如何去更快捷的适配不同手机的键值问题呢?也许按手机型号发布软件是一个最简单最直接的方案,局限性就是你必须知道每个平台的键值,希望MIDP3.0不要再有这个问题了。现在,我们就假设,我们已经能够获取到不同手机的键值,那么我们应该如何去写代码呢?在每一个 keyPressed里面设置switch case -6 / -7 / -5 的方法显然是不对的。 我们希望这样操作:
- package org.allove.weather.lib;
- ?
- public?class KeyMap {
- ? ? ///////////////
- ? ? public?static final int key_LeftSoft = -7 ;
- ? ? public?static final int key_RightSoft = -6 ;
- ? ? public?static final int key_OK = -5 ;
- ? ? public?static final int key_UP = -4 ;
- ? ? public?static final int key_DOWN = -3 ;
- ? ? public?static final int key_LEFT = -2 ;
- ? ? public?static final int key_RIGHT = -1 ;
- ? ? /////////////// 请注意 上面的键值只是为了测试 不一定正确
- }
- ?
- /////////////////////////////////////////
- ?// ..... Many Other Things ...
- import?package org.allove.weather.lib.KeyMap ;
- ?
- public?class ACanvas extends Canvas ;
- ?// ..... Many Other Things ...
- ? ? protected?void keyPressed(int key){
- ? ? ? ? if(key == KeyMap.key_LeftSoft){? ? ? ? ? ?
- ? ? ? ? ? ? do(.....) ;
- ? ? ? ? }?else if (key == KeyMap.key_OK){? ? ? ? ? ?
- ? ? ? ? ? ? do(.....) ;
- ? ? ? ? }?else if (key == KeyMap.key_RightSoft){? ? ? ? ? ?
- ? ? ? ? ? ? do(......) ;
- ? ? ? ? }?
- ? ? ? ? repaint();
- ? ? }
- ?// ..... Many Other Things ...
相信这样的代码结构是可读的,方便维护的,容易移植的 。 当你需要移植平台的时候只需要在KeyMap中修改映射即可。这也许就是OO思想的体现吧 。 好了今天就到这里吧 , 上面的代码基本都是框架,如果你希望得到源码的话可以留言并且发邮件到sunjianyes#gmail.com获取,如果你能记得我们那就{zh0}不过了。再如果你能够支持一下我们的发展就更好了,{zh0}的办法就是尝试使用我们的软件:
如果你在下次看到下面这张图片的时候能想起我们那就是我们{zd0}的成功: