我正在为关键字创建一个输入字段,而用户正在编写我在插入符号位置下方的列表中显示关键字的建议。
输入字段是单行,所以我使用向上/向下箭头键选择建议,然后按Enter键插入。
它主要起作用,但有一个很大的例外,即向上/向下键也会将插入符号位置更改为TextField
的开头/结尾。
我尝试在preventDefault()
事件监听器中使用stopImmediatePropagation()
和KeyboardEvent.KEY_DOWN
,我也用它来更改所选的建议,但这并没有改变任何内容。
当KeyboardEvent.KEY_DOWN
事件被触发时,我检查了carret还没有移动,视觉上我可以看到它在释放键之前正在移动(键入)。
我可以保存插入位置,然后重置默认行为。但这恰恰涉及一些使用计时器的类似黑客的代码。
那么有人知道如何防止默认行为吗?
答案 0 :(得分: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相关的好东西。
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。
答案 1 :(得分:4)
我在这里发布了这个问题的解决方法:
AS3: setSelection Up Arrow Override
答案 2 :(得分: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之前调用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为你做事的倾向。
答案 3 :(得分:1)
对于bug-a-lot的解决方案,可能会有一些轻弹效果。
使用此处描述的stage.invalidate()
和舞台Event.RENDER
有一个可行的解决方案和好方法:
答案 4 :(得分: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);
}
}
不性感但有效。
答案 5 :(得分: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();
}