4

我正在为关键字创建一个输入字段,当用户写作时,我在插入符号位置下方的列表中显示关键字建议。输入字段是单行的,所以我使用向上/向下箭头键选择一个建议,然后 Enter 插入它。它大部分都在工作,除了向上/向下键还将插入符号位置更改为TextField.

我尝试在事件侦听器中使用preventDefault()and来更改所选建议,但这并没有改变任何东西。我检查了触发事件时carret还没有移动,但是在视觉上我可以看到它在释放键之前正在移动(键向上)。stopImmediatePropagation()KeyboardEvent.KEY_DOWNKeyboardEvent.KEY_DOWN

我可以只保存插入符号的位置,然后重置为默认行为。但这将适当地涉及一些使用计时器的类似黑客的代码。

那么有谁知道如何防止默认行为?

4

6 回答 6

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 相关的好东西。

更新:对于 spark 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 。

于 2009-06-19T19:13:46.797 回答
4

我在这里发布了解决此问题的方法:
AS3: setSelection Up Arrow Override

于 2011-07-17T16:53:43.753 回答
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); 

请注意,我将处理每个键两次 - 在系统执行之前它是魔法(在 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 为你做事的偏好。

于 2009-06-22T23:37:43.367 回答
1

bug-a-lot 的解决方案可能会产生一些轻弹效果。

有一个有效的解决方案和使用这里描述stage.invalidate()的阶段的好技巧Event.RENDER

AS3:setSelection 上箭头覆盖

于 2013-01-28T15:25:47.113 回答
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);
    }
}

不性感,但它有效。

于 2009-06-19T23:18:29.673 回答
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();
}
于 2013-05-21T21:10:33.593 回答