程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> 小技巧——低級界面下的文本自動換行

小技巧——低級界面下的文本自動換行

編輯:J2ME

在應用中,有時候需要顯示大段的文字。如游戲中的幫助信息,以及RPG游戲的人物對白。對於這種大量文字的顯示,我們會很自然地想到使用高級界面的Form來顯示,好處就是簡單方便,我們不用去操心文字的斷行排版,Form會為你搞定一切。
但是,有時候我們無法使用高級界面,如游戲規定必須使用低級界面,再有就是RPG類的游戲也是必須要使用低級界面來顯示對白的。
使用低級界面顯示大段文字,關鍵在於你要把它給排好版。最直接的問題就是:一行可以顯示幾個字?
很多人這樣做:通過真機(必須用真機,模擬器不行的,會有差異)測量好一行能顯示幾個字,比如說7個。然後把大段的文字分成7個一行,變成了一個字符串數組,如:
final String[] strGameHelp = {
    "年份不詳的一個",
    "時代中,妖與人",
    "類都存在於世界",
    "上,並基本為對",
    "立狀態,但是不",
    "排除有相處一起",
    "的可能,因為人",
    "類基本已經接受",
    "世界上有妖的事",
    "實了。"
};
有了這麼一個字符串數組,我們就可以循環把它畫出來:
for(int i=0;i<strGameHelp.length;i++){
  g.drawString(strGameHelp[i],5,5+20*i,Graphics.TOP|Graphics.LEFT);
}
上NOKIA、SE、MOTO幾個模擬器一看,恩,不錯,很管用,效果很好。當下把幾個版本呼啦呼啦就全給搞定了。
當你正要端起杯子喝口水的時候,策劃跑了過來
K700的文字怎麼出框了
不可能啊,我量好了的,模擬器上看的好好的
不信你看……,策劃掏出了K700
你一看,果然出了框,看起來一行只能顯示6個字。
無奈,你開始挪字,改成:
final String[] strGameHelp = {
    "年份不詳的一",
    "個時代中,妖",
    "與人類都存在",
    "於世界上,並",
    "基本為對立狀",
    "態,但是不排",
    "除有相處一起",
    "的可能,因為",
    "人類基本已經",
    "接受世界上有",
    "妖的事實了。"
};
保存,編譯,打包發給策劃。
但策劃拒絕了文件傳送。
干嗎不收啊,你問。
還要改個東西,加一個字,改成“在年份不詳的……”,策劃告訴你。
你想了想,問策劃:能不能不改?
不能。策劃回答的很快,我也不想加的,某某領導要求的。
你無語。准備再開始挪字……
突然想:我不能老是改文字呀,萬一下次他跑過來說再加個什麼東西怎麼辦?
得想個法子搞定它。
於是寫了個函數:
final int CharacterNumber = 6;
public Vector getSubsection(String str){
  Vector vector = new Vector();
  int i=0;
  while(!str.equals(""){
    if(str.length>6){
      vector.addElement(str.substring(0,CharacterNumber));
      str = str.substring(CharacterNumber);
    }
    else{
      vector.addElement(str);
      str = "";
    }
  }
  return vector;
}
再把幫助信息改一改:
final String strGamehelp =
    "在年份不詳的一"+
    "個時代中,妖"+
    "與人類都存在"+
    "於世界上,並"+
    "基本為對立狀"+
    "態,但是不排"+
    "除有相處一起"+
    "的可能,因為"+
    "人類基本已經"+
    "接受世界上有"+
    "妖的事實了。";
最後是畫出來:
Vector vector = getSubsection(strGamehelp);
for(int i=0;i<vector.size();i++){
  g.drawString((String)vector.elementAt(i),5,5+20*i,Graphics.TOP|Graphics.LEFT);
}
vector = null;
這下好了,隨便加,怎麼加我都不怕,嘿嘿,自動換行。

到這是不是結束了?還沒。
一個月後,你開始做英文版,幫助信息改成了英文。你發現幫助界面是慘不忍睹。
原來,英文字母和中文不一樣,它是不等寬字體,有肥有瘦,發育不太均衡。
更重要的是,,英文中一個單詞是不能拆開分成兩行顯示。

怎麼辦。回過去用高級界面?想都不要想。
你打開API手冊查閱,希望能找出點什麼來。
有了,你眼前一亮,印入眼簾的正是Font類提供的stringWidth函數,該函數能夠返回字符串在屏幕上顯示時的長度。
有了這個函數,就可以改進getSubsection函數了
其中,strSource是待斷行的文字,font是畫文字時使用的字體,width是每行的最大寬度,而最後的strSplit是用於分詞的,即英文單詞中的間隔符號,函數依靠這個參數來分辨單詞。
   public Vector getSubsection(String strSource,Font font,int width,String strSplit){
     Vector vector = new Vector();
     String temp=strSource;
     int i,j;
     int LastLength = 1;
     int step = 0;
     try{
         while (!temp.equals("")) {
           i=temp.indexOf("\n");
           if(i>0){
             if(font.stringWidth(temp.substring(0,i-1)) >= width){
               i = -1;
             }
           }
           if(i==-1){
             if(LastLength>temp.length()){
               i = temp.length();
             }else{
               i = LastLength;
               step = font.stringWidth(temp.substring(0, i)) > width ? -1 : 1;
               if(i<temp.length()){
                 while (! (font.stringWidth(temp.substring(0, i)) <= width
                           && font.stringWidth(temp.substring(0, i + 1)) > width)) {
                   i = i + step;
                   if (i == temp.length())
                     break;
                 }
               }
             }
             if(!strSplit.equals("")){
               j = i;
               if (i < temp.length()) {
                 while (strSplit.indexOf(temp.substring(i-1,i))==-1) {
                   i--;
                   if (i == 0) {
                     i = j;
                     break;
                   }
                 }
               }
             }
           }
           LastLength = i;
           vector.addElement(temp.substring(0, i));
           if (i == temp.length()) {
             temp = "";
           }
           else{
             temp = temp.substring(i);
             if (temp.substring(0, 1).equals("\n")) {
               temp = temp.substring(1);
             }
           }
         }
     }catch(Exception e)
     {
       System.out.println("getSubsection:"+e);
     }
     return vector;
  }

再改一下調用的地方:
Font font  = Font.getFont(Font.FACE_SYSTEM,Font.STYLE_PLAIN, Font.SIZE_SMALL);
g.setFont(font);
Vector vector = getSubsection(strGamehelp,font,getWidth()-10," ,.?!");
這樣,對於英文我們也可以正確的自動斷行顯示了。

終於,你可以坐下來,喝杯水(咖啡被搶光了),聽點music,享受一下:
1、通用性好,自動適應不同的屏幕大小,各種語言文字通吃。
2、工作量小,你不用去辛苦手工分行,更不用為了加一個字而全部重新來過。想調整寬度?改一個參數就好。

然而,最最後不得不和你說,千萬要注意的是,一定要注意調用函數時使用的字體和實際使用的字體要一致,不然我會錯(我常犯這樣的錯誤:))

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved