4

キーワードの入力フィールドを作成しています。ユーザーが書いている間、キャレット位置の下のリストにキーワードの候補を表示しています。入力フィールドは 1 行なので、上下矢印キーを使用して提案を選択し、Enter を使用して挿入しています。そして、それはほとんど機能していますが、上/下キーもキャレット位置を.の先頭/末尾に変更するという大きな例外がありますTextField.

選択した提案を変更するためにも使用するイベントリスナーでpreventDefault()andを使用してみましたが、何も変わりません。イベントが発生したときにキャレットがまだ移動していないことを確認しましたが、キーが離される前 (キーアップ) にキャレットが移動していることを視覚的に確認できます。stopImmediatePropagation()KeyboardEvent.KEY_DOWNKeyboardEvent.KEY_DOWN

キャレットの位置を保存してから、デフォルトの動作にリセットすることができました。しかし、これにはタイマーを使用したハックのようなコードが適切に含まれます。

それで、デフォルトの動作を防ぐ方法を知っている人はいますか?

4

6 に答える 6

6

防ぐことはできませんが、元に戻すことはできます。これを行うには、同じイベント (KeyboardEvent.DOWN) に異なる優先度を持つハンドラーを追加します。1 つは TextField の の前に実行され、選択インデックスを保存し、もう 1 つは後で復元します。作業コードは次のとおりです。

    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.invalidate()、ステージEvent.RENDERはここで説明されています:

AS3:setSelection上矢印オーバーライド

于 2013-01-28T15:25:47.113 に答える
1

bug-a-lot による解決策は興味深いものです。優先順位を使用することは考えていませんでした。代わりに、イベント プロセスのさまざまなフェーズを利用しました。私にとっての問題は、矢印キーで特定のテキスト フィールド内の 1 文字を前進または後退させるか、フォーム内の次または前のフィールドにジャンプするかを決定することでした。

まず、キーのステージのイベント処理をオーバーライドします。

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); 

各キーを 2 回処理することに注意してください。システムがウィザードリを実行する前に (事前入力は 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 が何をしたかを判断し、元に戻してから、何をすべきかを実行します。私の関数「typing」には、この議論には必要のないものがたくさんありますが、重要なことは 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 に答える
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 に答える