How do you prevent the default behavior for increasing / decreasing the default in TextField?

I create an input field for keywords, and although users write, I display suggestions for a keyword in the list under the carriage. The input field is single-line, so I use the up / down arrow to select a sentence and Enter to insert it. And this basically works, with the big exception that the up / down key also changes the position of the carriage to the beginning / end of the TextField .

I tried using preventDefault() and stopImmediatePropagation() in the KeyboardEvent.KEY_DOWN event listener, which I also use to change the selected sentence, but that doesn't change anything. I checked that the carret was not moving yet, when the KeyboardEvent.KEY_DOWN event is fired, visually I see that it moves before the key is released (up key).

I could just save the carriage position and then reset af to the default. But this should include some kind of hacker code using a timer.

Does anyone know how to prevent default behavior?

+4
source share
6 answers

You cannot prevent this, but you can undo it. To do this, you add KeyboardEvent.DOWN to the handlers with different priorities in the same event. One will run before the TextField and save the selection indices, and the other after, restoring them. Below is the working code:

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

Perhaps you need better names for ssi (the index of the initial choice) and sei (the index of the end of the choice), I was lazy to find some. I think this decision was based on the post of Alex Harui, I donโ€™t remember exactly, but he had a lot of good material related to Flex on his blog.

UPDATE: For the TextInput spark, prevention is not only possible, but also very simple. All you have to do is catch the event in the capture phase and stop the spread. Code:

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

Note the last parameter in the addEventListener call, which is set to true, so that the handler is called in the capture phase. Unfortunately, this solution does not work for mx TextInput, only for spark.

+6
source

I posted a workaround for this problem:
AS3: setSelection Up Arrow Override

+4
source

The bug-a-lot solution is intriguing - I did not think to use priorities. Instead, I used different phases of the event process. The problem for me was to decide whether the arrow keys should advance or retreat a single character within a given text field or move to the next or previous field in the form.

First, I redefine the processing of stage events for keys:

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

Please note that I will process each key twice - before the system does this wizardry (pretyping is called before KEY_DOWN), so I can see where the carriage is before Flash moves it and after the system processes it ( using the input called after 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 is my method - all it does is turn these codes into convenient mnemonics. And isFocusInTextBox is a challenge to my focus manager - I replaced the standard focus manager to overcome other problems with Flash. I just need to know if this is a text box or not.

Then I need to process the key after Flash has already moved the caret and maybe even moved to a new field, and after looking at the previous state, decide what Flash is doing and cancel it, and then do what should happen. My typing function has many things that are not needed for this discussion, but the important thing that it does is call allowKeyMapping. allowKeyMapping decides whether the user enters the forward arrow (or down arrow) from the last character position in the text box or enters the back arrow from the very beginning. If so, "enter" will be displayed in the next or previous field, respectively.

  /** 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; } 

Sorry, I do not have a compact example. I just thought it was important to emphasize that you can get around the Flash addiction to do something for you, whether you want them to happen or not.

+1
source

There might be some kind of flick effect with a bug-a-lot solution.

There is a working solution and a good trick using stage.invalidate() and stage Event.RENDER described here:

AS3: setSelection Up Arrow Override

+1
source

This is my workaround for this problem. I'm sure there is a better way, but you probably need to extend the TextInput control.

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

Not sexy, but it works.

0
source

the default is priority 0 on the UIComponent so you can always stop the stop so that something happens, here you will prevent all KeyboardEvent.KEY_DOWN

 yourObject.addEventListener(KeyboardEvent.KEY_DOWN, _preventDefault, false, 1, true ); private function _preventDefault(event:KeyboardEvent):void { event.preventDefault(); event.stopImmediatePropagation(); } 
0
source

Source: https://habr.com/ru/post/1286468/


All Articles