2009-06-19 9 views
4

私はキーワードの入力フィールドを作成していますが、ユーザーが書いている間、私はキャレット位置の下のリストにキーワードの候補を表示しています。 入力フィールドは1行であるため、矢印の上下キーを使用して候補を選択し、Enterを押して挿入します。 ほとんどの場合、上下キーでキャレットの位置がTextFieldの始まり/終わりに変わるという大きな例外があります。TextFieldの矢印上/下のデフォルトの動作をどうやって防ぐのですか?

私はKeyboardEvent.KEY_DOWNイベントリスナーでとstopImmediatePropagation()を使用しようとしましたが、選択した候補を変更するのにも使用しましたが、何も変更されません。 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では動作しません。

+0

私はこれをFlashで作成しているので、TextInputの代わりにTextFieldを使用しています。 これを正しく動作させることができません。問題は、デフォルト動作の前にonAfterKeyDownが呼び出されているようです。 アイデア –

+1

onAfterKeyDownを低い優先度で追加してもよろしいですか?それが問題になるとは思わないが、-10000よりも小さい数字を試してみてください。 –

+0

はい、私は-10000とint.MIN_VALUEの両方で試しました。 –

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

セクシーではありませんが動作します。

+0

それは私にとってはうまくいかない。私は適切にポジションを保存し、デフォルトの動作を適用する必要があります。 –

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

注 - システムが行う前に、それは魔法だ(pretypingがKEY_DOWN前に呼び出される)ので、I Flashがそれを動かす前と、システムがそれを処理した後に、キャレットがどこにあるのかを見ることができます(入力時に、KEY_UPの後に呼び出されます)。

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の傾向に乗ることができることを強調することが重要だと思った。

+0

私は今これに似たものを持っていますが、KEY_UPを使用すると、時々キャレットがちょっと飛び跳ねることがあります。 私はそれを避けることを好むでしょう。 –

4

私はここで、この問題の回避策を掲載している:
AS3: setSelection Up Arrow Override

+0

彼のソリューションは完璧に動作します。 – xLite

+0

秒。アクションスクリプトだけのテキストフィールドでUp Arrowの動作を防止して私のために働いた – Flion

1

バグ-A-多くのソリューションといくつかのフリック効果があるかもしれません。あなたはここで、あなたは常に起こるために何かを停止する停止することができ、デフォルトのイベントによって

AS3: setSelection Up Arrow Override

0

がUIComponent に優先順位0以下のとおりです。

作業溶液との良好なトリックがstage.invalidate()を使用して、ステージのEvent.RENDERは、ここで説明がありますすべてを禁止するKeyboardEvent.KEY_DOWN

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