首页 | 博客群 | 公社 | 专栏 | 论坛 | 图片 | 资讯 | 注册 | 帮助 | 博客联播 | 随机访问
常用的排序算法(包括冒泡排序,选择排序,插入排序,希尔排序,快速排序)- -| 回首页 | 2007年索引 | - -欢迎大家加入我的J2me交流群,50011472,500人的超级群

低级界面中实现输入法

关键词低级界面 输入法 canvas                                          

呵呵,在游戏或者应用开发中,在高级界面和低级界面之间的切换总是一件让人头疼的事情,高级界面方便,但是难看,低级界面美观,但是一直以来因为在输入法上存在困难(主要是指中文),所以很多产品都是使用了两种界面并存的方式,但我一直想放弃高级界面,采用低级界面来保持产品界面风格的统一,经过N天的努力,终于整成了一套比较好用的输入法,从此可以告别高级界面了,^_^

先讲讲这个输入法的原理,首先程序会从字库文件中将拼音和相应的文字读进内存,其中拼音会放在一个数组里,用来查找,然后字库里的字会以拼音为Key存入一个哈希表,查找的时候,首先根据按键上的字母组合在拼音表里查找是否有适配的拼音,如果有完整适配的拼音则直接从哈希表从取出相应的文字以供选择,下面就给出相应的代码

public class InputMethod implements Const
{
 Hashtable hashtable=new Hashtable();
 String[] wordKey;
 int[] inputKey=new int[10];
 int currentPos;
 String[] currentInputPad;//当前的输入显示板
 public Vector keyAvailable=new Vector(0,1);
 Vector wordsBuffer;//上一级的读音的缓存
 int select,charSelect;
 int screenW,screenH;
 int num_row;//每行的字數
 int charPage;//頁數
 public String inputChar;//輸入的字符
 int inputMode;//输入类型 0字母 1数字 2拼音
 String[] inputModeTxt={"abc","123","拼音"};
 public String content[]={"","",""};//输入的内容,第一维是实际内容,第二维和第三维是用于有光标定位显示的内容
 public int charPos;//光标位置
 long time1,time2;//按键的时间
 int charKeyPos;//字母的切换
 String[][] charKey=new String[][]{
   {"a","b","c"},
   {"d","e","f"},
   {"g","h","i"},
   {"j","k","l"},
   {"m","n","o"},
   {"p","q","r","s"},
   {"t","u","v"},
   {"w","x","y","z"}
 };
 public InputMethod(int w,int h)
 {
  screenW=w;
  screenH=h;
  num_row=(w-10)/20;
  charPage=0;
  cls();
  readWords();
 }
 /*清空缓存*/
 public void cls()
 {
  currentPos=0;
  wordsBuffer=new Vector(0,1);
  for(int i=0;i<inputKey.length;i++)
   inputKey[i]=-1;
 }
 /*清空输入内容*/
 public void clsContent()
 {
  content=new String[]{"","",""};
  charPos=0;
  charSelect=0;
 }
 public void doUp()
 {
  if(select>0)
   select--;
  currentInputPad=null;
 }
 public void doDown()
 {
  if(select<keyAvailable.size()-1)
   select++;
  currentInputPad=null;
 }
 public void drawInput(Graphics g)
 {
  try
  {
   int starty;
   if(inputMode==2)
   {
    if(keyAvailable!=null&&keyAvailable.size()>0)
    {
     starty=240-keyAvailable.size()*20;
     if(keyAvailable.size()>0)
      PaintCanvas.drawBox(g, 0, starty, 50,keyAvailable.size()*20, 0xffff00);
     g.setColor(0);
     for(int i=0;i<keyAvailable.size();i++)
     {
      if(i==select)
       g.setColor(0x00ff00);
      else
       g.setColor(0x0000ff);
      g.fillRect(0,starty+i*18,50,18);
      g.setColor(-1);
      String key=(String)keyAvailable.elementAt(i);
      g.drawString(key,10,starty+i*18,0);
      if(i==select)
      {
       /*查找相应的拼音*/
       for(int m=0;m<wordKey.length;m++)
       {
        /*如果完全适配,就从哈希表里取出相应的字*/
        if(key.equals(wordKey[m]))
        {
         currentInputPad=(String[])hashtable.get(key);
         break;
        }
       }
      }
     }
    }

    if(currentInputPad!=null)
    {
     starty=screenH-65;
     drawTextBox(g,0xefefef,0x121212,0x2d3f4d,2,starty,screenW-4,25,2,0);
     g.setColor(0xffff00);
     for(int i=charPage*num_row;i<(charPage+1)*num_row;i++)
     {
      System.out.println(i+"."+charPage+"."+num_row+"."+charSelect);
      if(i>currentInputPad.length-1)
       return;
      if(i==charSelect)
      {
       g.setColor(-1);
       g.drawRect(3+(i-charPage*num_row)*20,starty+1,16,20);
      }
      g.setColor(0xffff00);
      g.drawString(currentInputPad[i],5+(i-charPage*num_row)*20,starty+2,0);
     }
    }
   }
   PaintCanvas.drawStringShadow(g,-1,0,0,inputModeTxt[inputMode],w,0,24);
  }
  catch(Exception e)
  {
   System.out.println("輸入法出錯"+e.toString());
  }
 }
 public void drawTextBox(Graphics g,int color1,int color2,int color3,int stx,int sty,int bw,int bh,int boardW,int type)
 {
  if(type==0)
  {
   g.setColor(color1);
   g.fillRect(stx-boardW,sty-boardW,bw+2*boardW,bh+2*boardW);  
   g.setColor(color2);
   g.fillRect(stx,sty,bw+boardW,bh+boardW);
   g.setColor(color3);
   g.fillRect(stx,sty,bw,bh);  
  }
  else
  {
   g.setColor(color2);
   g.fillRect(stx-boardW,sty-boardW,bw+2*boardW,bh+2*boardW);  
   g.setColor(color1);
   g.fillRect(stx,sty,bw+boardW,bh+boardW);
   g.setColor(color3);
   g.fillRect(stx,sty,bw,bh);  
  }   
 }
 public void keyPressed(int i)
 {
  time2=System.currentTimeMillis();
  if(i==MIDKEY)
  {
   if(inputMode==2)
   {
    if((inputChar=getChar())!=null)
    {
     cls();
     keyAvailable.removeAllElements();
     currentInputPad=null;
    }
   }
  }
  if(i==SOFTRIGHTKEY)
  {
   backWord();
//   cls();
//   keyAvailable=new Vector(0,1);
//   currentInputPad=null;
  }
  if(i>=48&&i<58)
  {
   if(inputMode==2&&i>=50)
   {
    if(checkWord(i-50))
    {
     inputKey[currentPos++]=i-50;
     currentInputPad=null;
    }
    select=0;
   }
   else if(inputMode==1)
    inputChar=""+(i-48);
   else if(inputMode==0)
   {
    if(i>=50)
    {
//     System.out.println("按键时间"+time2+"."+time1);
     if((time2-time1)<500)
     {
//      System.out.println("连续按键");
      charKeyPos++;
      if(charKeyPos==charKey[i-50].length)
       charKeyPos=0;
//      System.out.println("内容长度"+content[0].length()+"光标位置"+charPos);
      if(charPos==content[0].length())
      {
       System.out.println("1");
       content[0]=content[0].substring(0,charPos-1);
       charPos--;
       System.out.println("2");
      }
      else
       content[0]=content[0].substring(0,charPos-1)+content[0].substring(charPos,content[0].length());
      refreshContent();
     }
     inputChar=charKey[i-50][charKeyPos];
    }
   }
  }
  if(i==UPKEY)
   doUp();
  if(i==DOWNKEY)
   doDown();
  if(i==LEFTKEY)
  {
   if(charSelect>0)
    charSelect--;
   if(charSelect%num_row==num_row-1)
    charPage--;
  }
  if(i==RIGHTKEY)
  {
   if(charSelect<currentInputPad.length-1)
    charSelect++;
   if(charSelect%num_row==0&&charSelect!=0)
    charPage++;
  }
  /*切换输入法*/
  if(i==POUNDKEY)
  {
   inputMode++;
   if(inputMode==inputModeTxt.length)
    inputMode=0;
  }
  /*删除*/
  if(i==CKEY)
  {
   if(charPos>=2&&PaintCanvas.checkFace(content[0].substring(charPos-2,charPos))>-1)
   {

    content[0]=content[0].substring(0, charPos-2)+content[0].substring(charPos,content[0].length());
    charPos-=2;
   }
   else if(charPos>0)
   {
    if(charPos==content[0].length())
     content[0]=content[0].substring(0,charPos-1);
    else
     content[0]=content[0].substring(0, charPos-1)+content[0].substring(charPos,content[0].length());
    charPos--;
   }
   refreshContent();
  }
  time1=time2;
 }
 /*回退*/
 public void backWord()
 {
  if(wordsBuffer.size()>0)
  {
   keyAvailable=(Vector)wordsBuffer.elementAt(wordsBuffer.size()-1);
   wordsBuffer.removeElementAt(wordsBuffer.size()-1);
   currentInputPad=null;
  }
 }
 public void checkWords(Vector temp,String key,int ik)
 {
  int p;
  for(p=0;p<charKey[ik].length;p++)
  {

   int m;
   for(m=0;m<wordKey.length;m++)
   {
    if(wordKey[m].indexOf(key+charKey[ik][p])==0)
    {
     temp.addElement(new String(key+charKey[ik][p]));
     break;
    }
   }
  }
 }
 /*检查是否有合适的拼音*/
 public boolean checkWord(int ik)
 {
  Vector temp=new Vector(0,1);
  String key="";
  if(keyAvailable.size()>0)
  {
   for(int i=0;i<keyAvailable.size();i++)
   {
    key=(String)keyAvailable.elementAt(i);
    checkWords(temp,key,ik);
   }
  }
  else
   checkWords(temp,key,ik); 
  if(temp.size()>0)
  {
   wordsBuffer.addElement(keyAvailable);
   keyAvailable=temp;
   return true;
  }
  return false;
 }
 /*从字库里读取文件*/
 public void readWords()
 {
  try
  {
   InputStream is;
   String[] words;
   int fontNum=0;
   is=getClass().getResourceAsStream("/input/chars.txt");
   StringBuffer sb=new StringBuffer();
   int c;
   int pos=0;
   while((c=is.read())!=-1)
   {
//    System.out.println(c);
    if(c=='\n')
    {
     if(pos==0&&fontNum==0)
     {
      fontNum=Integer.parseInt(sb.toString());
      wordKey=new String[fontNum];
//      System.out.println("拼音表长度:"+wordKey.length);
     }
     else
     {
      String key;
      byte[] data1=new byte[sb.toString().length()];
      for(int i=0;i<data1.length;i++)
       data1[i]=(byte)sb.charAt(i);
      String s=new String(data1,"UTF-8");
      key=s.substring(0, s.indexOf("*")).toLowerCase();
//      System.out.println(key);
      words=new String[s.length()-s.indexOf("*")-1];
      for(int j=0;j<words.length;j++)
      {
       words[j]=s.substring(s.indexOf("*")+1+j,s.indexOf("*")+2+j);
      }
      hashtable.put(key, words);
      wordKey[pos++]=key;  
     }
     sb=new StringBuffer();
    }
    else if(c!=0x0d)
    {
     sb.append((char)c);
    }
   }
   String key;
   byte[] data1=new byte[sb.toString().length()];
   for(int i=0;i<data1.length;i++)
    data1[i]=(byte)sb.charAt(i);
   String s=new String(data1,"UTF-8");
   key=s.substring(0, s.indexOf("*"));
   words=new String[s.length()-s.indexOf("*")-1];
   for(int j=0;j<words.length;j++)
   {
    words[j]=s.substring(s.indexOf("*")+1+j,s.indexOf("*")+2+j);
   }
   hashtable.put(key, words);
   wordKey[pos++]=key;
  }
  catch(Exception e)
  {
   System.out.println("读取字库出错"+e.toString());
  }
 }
 public String getChar()
 {
  if(currentInputPad!=null)
   return currentInputPad[charSelect];
  else
   return null;
 }
 public void setInputMode(int type)
 {
  inputMode=type;
 }
 public int getInputMode()
 {
  return inputMode;
 }
 public void refreshContent()
 {
  if(content[0].length()>0)
  {
   if(charPos==0)
   {
    content[1]=" "+content[0];
    content[2]="|"+content[0];
   }
   else if(charPos==content[0].length())
   {
    content[1]=content[0]+" ";
    content[2]=content[0]+"|";
   }
   else
   {
    content[1]=content[0].substring(0,charPos)+" "+content[0].substring(charPos,content[0].length());
    content[2]=content[0].substring(0,charPos)+"|"+content[0].substring(charPos,content[0].length());
   }
  }
  System.out.println(content[0]);
  System.out.println(content[1]);
  System.out.println(content[2]);
 }
 /*移动光标*/
 public void moveCharPos(int direct)
 {
  if(direct==0)
  {
   if(charPos>2)
   {
    System.out.println(content[0].substring(charPos-2,charPos));
    if(PaintCanvas.checkFace(content[0].substring(charPos-2,charPos))>-1)
     charPos-=2;
    else
     charPos--;
   }
   else if(charPos>0)
    charPos--;
  }
  else
  {
   if(charPos<content[0].length()-2)
   {
    if(PaintCanvas.checkFace(content[0].substring(charPos+1,charPos+3))>-1)
     charPos+=2;
    else
     charPos++;
   }
   else if(charPos<content[0].length())
    charPos++;
  }
  refreshContent();
 }
}

这个代码实现了用#号键切换英文,数字,拼音之间的输入法切换(不好意思,暂时没有加入标点输入),然后在自己的Canvas界面中通过如下按键控制

 /*输入法的按键*/
 public void keyPressedInput(int i)
 {
  if(!chooseFace&&down&&imt.keyAvailable.size()==0)
  {
   chooseFace=true;
   faceNo=7;
  }
  else if(!chooseFace&&left&&imt.keyAvailable.size()==0)
  {
   imt.moveCharPos(0);
  }
  else if(!chooseFace&&right&&imt.keyAvailable.size()==0)
  {
   imt.moveCharPos(1);
  }
  else if(chooseFace)
  {
   if(left)
   {
    if(faceNo==0)
     faceNo=face.rows*face.columns-1;
    else
     faceNo--;
   }
   else if(right)
   {
    if(faceNo==face.rows*face.columns-1)
     faceNo=0;
    else
     faceNo++;
   }
   else if(up)
    chooseFace=false;
   else if(fire||softLeft)
   {
    imt.content[0]+=faceSign[faceNo];
    imt.charPos+=2;
    imt.refreshContent();
   }
  }
  else if(softRight)
  {
   if(imt.keyAvailable==null||imt.keyAvailable.size()==0)
   {
    drawMessage=-1;
    imt.clsContent();
   }
   else
    imt.keyPressed(-7);
  }
  else if(softLeft)
  {
   if(imt.keyAvailable.size()==0)
   {

    if(imt.content[0]!=null&&imt.content[0].length()>0)
    {
     sendMessage(drawMessage);
    }
    else
     setNotice("对不起,你输入的信息为空");
    drawMessage=-1;
   }
  }
  else
  {
   imt.keyPressed(i);
   if(imt.inputChar!=null)
   {
    if(imt.content[0]==null||imt.content[0].length()==0)
    imt.content[0]=imt.inputChar;
    else
     imt.content[0]=imt.content[0].substring(0,imt.charPos)+imt.inputChar+imt.content[0].substring(imt.charPos, imt.content[0].length());
    imt.inputChar=null;
    imt.charPos++;
   }
  }
  imt.refreshContent();
 }

这里面有一些我自己的工程中要用到的类,大家看的时候注意区分一下,呵呵,比如chooseFace是为了我们这边需要插入表情头像用的,大家可以不用,绘制的时候,交替显示inputmethod里的content[1]和content[2],确定需要用到输入内容的时候,调用inputmethod里的content[0]就行了。

另外给一下字库文件的格式

392
A*啊阿腌
Ai*爱矮挨哎碍癌艾唉哀蔼隘埃皑呆嫒暧捱

字库文件是一个TXT文件,第一行的数字标明这个字库里有多少拼音,然后每一行是拼音和字库,这个文件可以自己随意定义。

OK,就说这么多吧,大家有看不明白的地方,可以找我交流一下,谢谢。

【作者: 刀剑啸】【访问统计:】【2007年05月16日 星期三 14:25】【注册】【打印

搜索

Google

Trackback

你可以使用这个链接引用该篇文章 http://publishblog.blogchina.com/blog/tb.b?diaryID=6277574

回复

- 评论人:广州|C   2008-08-04 09:37:10   

想问一下,用手机自带的输入法不能用吗?还要自己写一个?

- 评论人:anouymous   2007-05-18 17:41:40   

内嵌组件是什么东西?

- 评论人:刀刀   2007-05-17 15:40:15   

回答一下,内嵌组件的界面很不好看,不符合游戏的风格,至于字库,目前4000来字是14K

- 评论人:anonymous   2007-05-16 19:10:14   

什么编码-8?
这字库要多大啊?

- 评论人:anonymous   2007-05-16 16:51:17   

为什么不用内嵌组件呐

验证码:   
评论内容: