2009-06-19 71 views
4

我正在爲關鍵字創建一個輸入字段,而當用戶正在寫關鍵字時,我在插入符號位置下方的列表中顯示關鍵字的建議。 輸入字段是單行,所以我使用箭頭向上/向下鍵選擇一個建議,然後按Enter鍵以插入它。 它主要工作,除了上/下鍵還將插入符號的位置更改爲TextField的開始/結尾。如何防止TextField中的向上/向下箭頭默認行爲?

我已經嘗試在KeyboardEvent.KEY_DOWN事件偵聽器中使用preventDefault()stopImmediatePropagation(),我也用它來更改選定的建議,但這不會改變任何內容。 我檢查了carret尚未移動時,KeyboardEvent.KEY_DOWN事件被觸發,視覺上我可以看到它正在鍵被釋放之前(鍵)。

我可以保存插入位置,然後重置默認行爲。但是,這將正確地涉及一些使用計時器的類似黑客的代碼。

那麼有誰知道如何防止默認行爲?

回答

6

你不能阻止它,但你可以扭轉它。爲此,您將具有不同優先級的處理程序添加到同一事件 - KeyboardEvent.DOWN。一個將在TextField之前執行,並保存選擇索引,另一個在恢復之後執行。工作代碼如下:

import flash.events.Event; 
    import flash.events.KeyboardEvent; 
    import flash.ui.Keyboard; 

    import mx.controls.TextInput; 
    import mx.events.FlexEvent; 

    public class FooledTextInput extends TextInput 
    { 
     private var ssi : int = 0; 
     private var sei : int = 0; 

     public function FooledTextInput() 
     { 
      super(); 

      this.addEventListener(KeyboardEvent.KEY_DOWN, onBeforeKeyDown, false, 10000); 
      this.addEventListener(KeyboardEvent.KEY_DOWN, onAfterKeyDown, false, -10000); 
     } 

     private function onBeforeKeyDown(e : KeyboardEvent) : void 
     { 
      if (e.keyCode == Keyboard.UP || e.keyCode == Keyboard.DOWN) 
      { 
       ssi = this.selectionBeginIndex; 
       sei = this.selectionEndIndex; 
      } 
     } 

     private function onAfterKeyDown(e : KeyboardEvent) : void 
     { 
      if (e.keyCode == Keyboard.UP || e.keyCode == Keyboard.DOWN) 
      { 
       this.setSelection(ssi, sei); 
      } 
     } 
    } 

您可能需要爲SSI更好的名稱(選擇起始索引)和SEI(選擇結束索引),我是懶得找一些。 我認爲這個解決方案是基於Alex Harui的一篇文章,我不太清楚,但他的博客上有很多與Flex相關的好東西。

更新:對於火花TextInput,防止不僅是可能的,它很容易。您只需在捕獲階段捕獲事件並停止傳播。代碼:

package 
{ 
    import flash.events.KeyboardEvent; 
    import flash.ui.Keyboard; 

    import spark.components.TextInput; 

    public class HackedTextInput extends TextInput 
    { 
     public function HackedTextInput() 
     { 
      super(); 
      addEventListener(KeyboardEvent.KEY_DOWN, onBeforeKeyDown, true); 
     } 

     private function onBeforeKeyDown(e:KeyboardEvent) : void 
     { 
      if (e.keyCode == Keyboard.UP || e.keyCode == Keyboard.DOWN) 
      { 
       e.stopImmediatePropagation(); 
      } 
     } 
    } 
} 

注中的addEventListener調用,它設置爲true,以便處理程序的最後一個參數在捕捉階段被調用。令人遺憾的是,這個解決方案不適用於mx TextInput,僅適用於Spark。

+0

我在Flash中,所以我使用TextField而不是TextInput。 我無法讓這個工作正常,問題似乎是onAfterKeyDown在默認行爲之前被調用。 有什麼建議嗎? – 2009-06-23 12:16:27

+1

您確定要添加低優先級的onAfterKeyDown嗎?嘗試一個比-10000更低的數字,但我認爲這不是問題。 – 2009-06-23 12:28:35

+0

是的,我試着-10000和int.MIN_VALUE。 – 2009-06-24 08:53:21

0

這是我解決這個問題的方法。我確信有更好的方法,但它可能需要擴展TextInput控件。

private function onKeyDown(event:KeyboardEvent):void 
{ 
    if(event.keyCode == flash.ui.Keyboard.UP) 
    { 
     var begin:int = textinput.selectionBeginIndex; 
     var end:int = textinput.selectionEndIndex; 
     textinput.setSelection(begin,end); 
    } 
} 

不性感,但它的作品。

1

由bug-a-lot解決方案很有趣 - 我沒有想到要使用優先級。相反,我利用了事件過程的不同階段。對我來說,問題是要決定箭頭鍵是否應該在給定的文本字段內前進或後退一個字符,或跳轉到表單中的下一個或上一個字段。

首先,我重寫階段的事件處理的按鍵:

stage.addEventListener(KeyboardEvent.KEY_UP, typing); 
// Sneak in before the normal processing handles right and left arrow keystrokes. 
stage.addEventListener(KeyboardEvent.KEY_DOWN, pretyping, true, 10); 

注意,我會兩次處理每一個按鍵 - 該系統確實之前它的魔力(pretyping是KEY_DOWN之前調用),所以我可以在Flash移動之前看到插入符號的位置,然後在系統處理之後(鍵入KEY_UP之後調用)。

/** Capture prior state of text field so we can later tell if user should tab to next field or previous field. */ 
private function pretyping(evt:KeyboardEvent):void { 
    var keyString:String = Configuration.getKeyString(evt); 
    if (isFocusInTextBox()) { 
     var tf:TextField = getFocus() as TextField; 
     capturePhaseCaret = tf.caretIndex; 
    } 
} 

getKeyString是我的一個方法 - 它所做的就是將這些代碼轉換爲便捷的助記符。 isFocusInTextBox是對我的焦點經理的調用 - 我替換了標準焦點管理器以克服其他Flash問題。我只需要知道這東西是否是文本字段。

接下來,我必須在Flash已經移除插入符後才能處理密鑰,甚至可以跳到新字段,並通過查看以前的狀態,決定Flash執行的操作並撤消它,然後執行應執行的操作發生。我的函數「打字」有很多這個討論不需要的東西,但它所做的重要事情是調用allowKeyMapping。 allowKeyMapping決定用戶是否從文本字段的最後一個字符位置輸入向前箭頭(或向下箭頭),或從頭開始輸入向後箭頭。如果是這樣,「打字」將分別標籤到下一個或前一個字段。

/** Prefer default behavior and do not allow certain kestrokes to be reinterpreted by key mappings, such as left and right cursor keys in text boxes. */ 
    private function allowKeyMapping(keyString:String) { 
     var allow:Boolean; 
     // If focus is in a text field, allow right arrow to advance to next field only if caret is at end of text. 
     // Conversely, allow left arrow to back up to previous field only if caret is at beginning of text. 
     // The trick is that the normal processing of keystrokes by TextFields occurs before this method is called, 
     // so we need to know the caret position from before the key was pressed, which we have stored in capturePhaseCaret, set in pretyping. 
     if (isDragging) { 
      allow = false; 
     } 
     else if (isFocusInTextBox()) { 
      var tf:TextField = getFocus() as TextField; 
      if (keyString == Configuration.LEFT_CURSOR_KEY) { 
       allow = tf.caretIndex == 0 && capturePhaseCaret == 0; 
      } 
      else if (keyString == Configuration.RIGHT_CURSOR_KEY) { 
       allow = tf.caretIndex == tf.text.length && capturePhaseCaret == tf.text.length; 
      } 
      else { 
       allow = true; 
      } 
     } 
     else { 
      allow = true; 
     } 
     return allow; 
    } 

對不起,我沒有準備好一個簡潔的例子。我認爲重要的是要強調,無論您是否希望它們發生,您都可以繞過Flash的偏好來爲您做事。

0

默認事件UIComponent上 是優先級爲0,因此您可以隨時停止阻止一些事情發生,在這裏你防止所有KeyboardEvent.KEY_DOWN

yourObject.addEventListener(KeyboardEvent.KEY_DOWN, _preventDefault, false, 1, true); 
private function _preventDefault(event:KeyboardEvent):void 
{ 
event.preventDefault(); 
event.stopImmediatePropagation(); 
} 
相關問題