記得馮·諾依曼大神曾經對我們這些後輩說過,電腦是由運算器、控制器、儲存空間、輸入裝置和輸出裝置五大部分組成的。我們看看現如今的手機(mobile device),可以看到前面所述五大部分一樣不少,這就是所謂的麻雀雖小,五髒俱全。但是由於裝置的限制,手機在輸入、輸出裝置上有很大的限制,在今天要談到的使用者輸入響應上,於是就只由兩種了,一個是手機按鍵,另一個是觸控螢幕。
在J2ME下,Canvas可以響應按鍵事件與觸控螢幕事件,它封裝了六個protected的方法,響應六種不同的事件:keyPressed(int keyCode)用於響應按鍵壓下、keyReleased(int keyCode)用於響應按鍵釋放、keyRepeated(int keyCode)用於響應按鍵長時間壓下不釋放;pointerDragged(int x,int y)用於響應觸控螢幕拖拽、pointerPressed(int x,int y)用於響應觸控螢幕點擊、pointerReleased(int x,int y)用於響應觸控螢幕釋放。其中參數方面,keyCode告訴我們哪個按鍵觸發的事件,x、y分別告訴我們觸控螢幕被點擊的座標(絕對位置)。
在Android下,View同樣可以響應以上兩種事件,分別有:boolean onKeyDown(int keyCode,KeyEvent event)用於響應按鍵點擊、boolean onKeyMultiple(int keyCode, int repeatCount,KeyEvent event)用於響應按鍵重複點擊、boolean onKeyUp(int keyCode,KeyEvent event)用於響應按鍵釋放以及onTouchEvent(MotionEvent event)用於響應觸控螢幕事件。官方API指出onKeyMultiple方法總是返回false的,即它沒有handle,因此必須重寫才能實現。
在鍵盤事件方面,J2ME與Android的區別在於Android中定義了KeyEvent這個類,用於描述按鍵事件。這個KeyEvent可不簡單,它能夠將一個按鍵事件描述的淋漓盡致。它的getAction()方法,可以得到按鍵的行為(down、up or multiple);它的getDownTime()可以得到最近一次keyDown事件發生的時間;它的getEventTime()可以得到本次事件發生的時間;它的getRepeatCount() 可以得到同一按鍵被連續點擊的次數(這個很大程度上是為onKeyMultiple方法設計的)。經過我的實踐,我認為有一點是非常需要注意的,Android底層在觸發keyDown事件時,有一點與J2ME很不一樣:比如我們按下一個鍵但不釋放,J2ME只觸發一次keyDown事件由keyPressed()執行,然後就交給keyRepeated()處理,然而Android是每隔一段時間(幾十毫秒)就觸發一次,onKeyDown方法會連續響應事件,造成意想不到的事情。想解決這個問題倒也不難,你可以通過getAction判斷這次事件是否是keyDown,如果是的話,用getEventTime()減去getDownTime(),如果這個數值太小,可以選擇不響應。這個方法簡單,但是如果使用者輸入太快,真正的輸入也可能被忽略掉,所以還有另外一種方法:維護一個堆棧,在重寫onKeyDown()與onKeyUp()方法的時候,如果getAction()是keyDown,就入棧,如果是keyUp,就出棧,如果得到一個事件,當它是keyDown的時候,如果當前棧頂是keyDown,就選擇性不響應這個事件,這樣的話,長點擊就相當於一次點擊。其實有一些view的子類,比如Button加入了onLongClick()的處理方法這樣即使你用選中這個view,長時間按下選擇鍵,也可以相應的處理。
在觸控螢幕方面,Android只有onTouchEvent()來處理,但是由於它的參數中有MotionEvent,所以J2ME下分開的三種事件可以通過MotionEvent的getAction()方法加以區分。比較有意思的是MotionEvent中有一個getPressure()方法,能夠得到點擊的壓力,看來Android手機的元件精密程度很高,乃至軟體可以得到壓力的大小並通過它來做一些邏輯。
還有一點,Android的KeyEvent與MotionEvent是可以自己構造的,KeyEvent可以通過dispatch()方法將自己傳遞給KeyEvent的Callback,即事件響應處理方法,這樣就能讓我們做一個軟鍵盤出來(乍看起來比做windows軟鍵盤簡單,其實也並不容易,要是把它作為一個Activity跑得話,焦點問題還很麻煩),也可以做許多別的事情,這一點J2ME好像沒有做到。
對兩者輸入事件響應的比較就到這裡了,謝謝!