我正在为关键字创建一个输入字段,而用户正在编写我在插入符号位置下方的列表中显示关键字的建议。 输入字段是单行,所以我使用向上/向下箭头键选择建议,然后按Enter键插入。 它主要起作用,但有一个很大的例外,即向上/向下键也会将插入位置更改为 TextField 的开头/结尾。

我尝试在 KeyboardEvent.KEY_DOWN 事件监听器中使用 preventDefault() stopImmediatePropagation(),我也用它来更改选择的建议,但这不会改变任何东西。 当我发现 KeyboardEvent.KEY_DOWN 事件时,我检查了carret还没有移动,视觉上我可以看到它在释放键之前正在移动(键入)。

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

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

有帮助吗?

解决方案

你不能阻止它,但你可以扭转它。为此,您可以向同一事件添加具有不同优先级的处理程序 - 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相关的好东西。

UPDATE:对于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 one。

其他提示

我已在此处发布了此问题的解决方法:
AS3:setSelection向上箭头覆盖

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之前调用pretyping),这样我就可以在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为你做事的倾向。

对于bug-a-lot的解决方案,可能会有一些轻弹效果。

使用 stage.invalidate()和舞台的 Event.RENDER 有一个可行的解决方案和好方法:

AS3:setSelection向上箭头覆盖

这是我解决该问题的方法。我确信有更好的方法,但可能需要扩展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);
    }
}

不性感但有效。

默认情况下,事件在UIComponent上为优先级0 所以你可以随时停止发生某些事情,这里你要阻止所有的KeyboardEvent.KEY_DOWN

yourObject.addEventListener(KeyboardEvent.KEY_DOWN, _preventDefault, false, 1, true );
private function _preventDefault(event:KeyboardEvent):void 
{
event.preventDefault();
event.stopImmediatePropagation();
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top