2009-06-19 47 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(); 
} 
相关问题