顯示具有 Hide Virtual Keyboard 標籤的文章。 顯示所有文章
顯示具有 Hide Virtual Keyboard 標籤的文章。 顯示所有文章

2017年5月22日 星期一

在 Android 的 Edit 中, 如何按下 Enter 即隱藏虛擬鍵盤

在 Windows 的應用程式中,我們常常為了讓使用者能夠快速輸入,在Edit元件中的onKeyUp或者 onKeyDown 事件中主動偵測使用者輸入的字元是否有換行符號 (Enter),當使用者按下了Enter,程式碼就主動把游標 Focus 帶到下個欄位,但在行動裝置中,又多了一個課題:『如果是多個欄位,就帶到下個欄位。但如果是單一欄位,或是最後一個欄位,就隱藏虛擬鍵盤』

這個課題筆者在 2014九月的筆記『Virtual Keyboard 的顯示與隱藏』裡面已經有介紹過一次,只是當時是聚焦在iOS系統上,因為當時筆者開發的平台大都聚焦在iOS,對Android系統的關切並不多。

最近在一些專案中,也把觸角伸到了Android平台,但筆者仍堅持『不到最後關頭,絕不輕言JAVA』的原則,認識筆者的朋友們也都知道,筆者會寫,但非不得已,絕不寫JAVA的原則。

加上Delphi從XE6之後,對Android的支援也很深入了,筆者就更能堅定這個立場。

言歸正傳,在TEdit元件中要在使用者按下虛擬鍵盤的Enter鍵時,隱藏虛擬鍵盤的話,要怎麼做呢?

顯然用2014九月那個作法(把focus轉移到別的元件), 對Android平台沒用,不然筆者也不用多寫這篇筆記了。

是的,熟習Android的使用者都知道,按下Android的實體Back鍵,就能隱藏虛擬鍵盤。所以這個作法也很簡單,就是『在onKeyUp事件中,把Key 改成 137 即可』

onKeyUp 事件中,有兩個 call by Reference 的參數,一個是 Key, 另一個是 KeyChar, 都讓我們可以在處理完鍵盤事件後,重新賦予新的值給系統。在Delphi Seattle, Berlin, Tokyo (前面的版本我已經移除了,無從驗證),這三個比較新的版本中,都定義有 vkHardwareBack這個值,其數值就是 137。

只需在 onKeyUp 事件中把 137 指派給 Key 這個變數即可隱藏鍵盤了,但通常我們程式碼可能會用於多種平台上,所以我的範例程式碼會加上 {$IFDEF Android} 這樣的判別式,以利多平台的程式維護:

procedure TFormMain.Edit_changeDeviceNameKeyUp(Sender: TObject; var Key: Word;
    var KeyChar: Char; Shift: TShiftState);
begin
   if Key = vkReturn then begin
      self.btn1.SetFocus;

{$IFDEF ANDROID}
      Key := vkHardwareBack
{$ENDIF}
   end;
end;
這樣應該很容易理解,對嗎?

2014年7月12日 星期六

FireMonkey - 行動裝置上虛擬鍵盤的出現與隱藏

在 Win32 的應用程式開發中, VCL 架構當中, 我們常常會在畫面上有多個 TEdit 或 TMemo 的時候, 設定這些元件的 TabOrder, 用以決定每個文字編輯元件的順序, 待使用者輸入文字後,按下Tab鍵,便可切換到下一個文字輸入元件。

在行動裝置上卻沒有所謂以Tab鍵進行文字輸入元件切換的功能,要不是在虛擬鍵盤或手寫輸入控制元件上緣有上一個、下一個的按鍵進行切換,就會直接在鍵盤或手寫輸入框裏有換行、完成的按鍵,待使用者按下之後切換到下一個輸入的文字框去。

不僅如此,在行動裝置上輸入文字時,還會因為虛擬鍵盤的出現,需要把畫面整個向上挪移,才不會有文字框被虛擬鍵盤擋住,使用者輸入了什麼都看不見的窘況。

在 FireMonkey 的 TEdit,TMemo,就是扮演文字輸入框的角色,然而遍尋這兩個元件的所有Event,卻也找不著要如何達成前述切換文字輸入框的相關事件,更別提要像obj-c提供個像是 textFieldBeginEdit 這樣的Delegate method來偵測虛擬鍵盤的出現了。

雖然在TEdit裡面有onChange,onKeyUp,onKeyDown,onTyping這些事件,但這些事件卻無法接收到虛擬鍵盤的Return被觸發的事件,當然Windows系統上的Return可以測得,但行動裝置的不行,所以很令人煩躁。

然而,在FireMonkey 中,還是能夠達到前述功能的,只是要多花一些功夫,稍微多幾個步驟就是了:

KillFocusByReturn
這個屬性(property)是 TEdit 的新屬性,在設定接受到虛擬鍵盤的 Return 值時,是否要停止編輯,並讓目前的TEdit 失去Focus,這個屬性預設值是false,我們要把它改設定成true。

這樣一來,按下虛擬鍵盤的Return時,虛擬鍵盤就會自動縮回去了,也就是該文字框完成了編輯。

 

















































































TEdit 與鍵盤相關的新屬性
                        
TEdit 的事件


onEnter 事件
在每一個TEdit的事件表裡面,都有 onEnter 跟 onExit 這兩個事件,可以偵測到行動裝置上,該欄位是否開始/結束編輯了」

我們得自己計算一下每個TEdit 進入編輯模式時,該TEdit會不會被擋到?以iPad 為例,iPad的虛擬鍵盤(橫向)高度約為250,所以我會在橫向畫面最底下的TEdit 的 onEnter 事件當中設定一個畫面座標向上挪移250的動作:

procedure THeaderFooterForm.Edit1Enter(Sender: TObject);
begin
   shiftY := -150;
end;

設定了-150 的Y軸位移量之後,接著要偵測虛擬鍵盤出現與消失的事件:onVirtualKeyboardShow, onVirtualKeyboardHidden 這兩個事件,別急,看完再去寫 code。

Form 的虛擬鍵盤顯示/隱藏事件

onVirtualKeyboardShow, onVirtualKeyboardHidden 這兩個事件並不是歸屬給單一 TEdit 或TMemo 的哦,它們是歸屬於 TForm 的事件。

所以,我們接下來要先點選 TForm 元件,找到 onVirtualKeyboardShow, onVirtualKeyboardHidden 這兩個事件,雙擊它們,來製作出處理這兩個事件的事件處理常式。

如果Form 的畫面是由一個 align 設定為全螢幕(alClient)的TTabControl 元件所構成的,則在 onVirtualKeyboardShow 這個事件裡,我們要先把 TTabControl 元件的 align 屬性改設定為 alNone,否則修改其Position.Y 就不會有任何效果。

出現虛擬鍵盤
輸入完畢以後, 恢復原位














接著,把TTabControl Position.Y 設定為 ShiftY,就會看到畫面向上移動,露出正在輸入當中的 TEdit 或 TMemo 了。

最後,onVirtualKeyboardHidden 的時候,只要把 Position.Y 設定為 0,畫面就會恢復正常了。


心得分享:每一個文字輸入框的 ShiftY 都是獨立的,不用去管其他文字框的位移量是多少,彼此並沒有交互作用。


範例程式: 下載點