【发布时间】:2026-01-16 17:50:01
【问题描述】:
我正在为我的 Flex 移动应用程序开发一个简单的自动完成功能。为此,我有一个触发 Callout 的 CalloutButton。 标注包含一些列表,用户可以从中选择项目。在选择项目时,标注被关闭(calloutButton.closeDropDown())。
TextInput 的行为完全相同。用户输入文本,标注打开,根据输入的文本,列表发生变化。到目前为止工作正常。现在,当用户从任何列表中选择一个项目时,标注将关闭。也很好。 现在的问题是,在标注关闭后,TextInput 会自动重新获得焦点。
在移动设备上,这不仅令人不安。
我将此行为范围缩小到移动 TextInput 外观 (spark.skins.mobile.TextInputSkin),因为没有此外观类的 TextInput 不会显示此行为。
现在您可能会说只使用默认皮肤,但不幸的是我不能。默认皮肤在 Android 设备上存在一个错误,无法通过 enter 事件。我可以忍受,因为我不一定依赖于 enter 事件,但是,即使在打开标注后,spark 移动皮肤允许继续在 TextInput 中输入文本,这是迫切需要的,因为列表会根据输入的文本。
我无法提供任何代码,因为问题已经缩小到 skinClass,因此不应该出现在我自己的代码中。相信我,我尝试了所有好的和不太好的方法来防止 TextInput 再次获得焦点,但没有任何效果。
所以,完全卡在这里! 希望大家对如何解决这个问题有一些想法。
编辑: 在我的应用程序行为的步骤下方。 (公平地说,标注内的工作流程有点复杂,我在这里使用了几个列表和一个 SplitViewNavigator(因此不能使用 Flextras 自动完成),但这不会影响我的 TextInput 焦点问题米面)。
- 在 TextInput 中输入文本
- 在按键更改时打开带有两个列表的标注。
- 第一个 List 根据从 web 服务输入的文本接收结果
- 用户从列表中选择项目
- 第二个列表根据来自 web 服务的第一个列表的选择接收结果
- 用户选择第二个列表中的项目
- 标注关闭
这一切都很好,除了 TextInput 在 Callout 关闭后接收焦点。 我真的不知道是什么触发了这种行为。
Edit2:进一步说明问题的代码。 当然,这被剥离为最基本的内容,但它反映了组件和焦点的行为。
首先是可以控制Callout的CalloutButton和TextInput:
<ui:SearchCallout id="detailSearch"/>
<s:TextInput id="searchInput" skinClass="spark.skins.mobile.TextInputSkin"
enter="historySearch(searchInput.text)"
focusOut="searchFocusOutEvent(event)"
focusIn="searchFocusInEvent(event)"/>
TextInput 的焦点处理程序不做任何与标注相关的事情,它们只是设置另一个组件的当前状态,所以我将它们留在这里。
函数 historySearch 关闭 CallOut(我强制它关闭,因为它不会使用通常的 closeDropDown() 关闭),格式化搜索文本,处理 searchHistory 并最终触发搜索函数,将格式化的搜索文本传递给选定的组件。 以下是本案例的重要部分:
private function historySearch(val:String):void {
detailSearch.forceClose=true;
detailSearch.closeDropDown();
searchEvent(_searchSyms, true);
}
注意:'val'(TextInput 的文本)被修剪,最终会产生一个字符串数组,由 '_searchSyms' 表示。
更多事件监听器如下:
searchInput.addEventListener(KeyboardEvent.KEY_DOWN, onKeyEvent);
searchInput.addEventListener(FlexEvent.VALUE_COMMIT, onKeyEvent);
searchInput.addEventListener(TextOperationEvent.CHANGE, onTextChange);
KEY_DOWN 和 VALUE_COMMIT 与 Callout 没有任何关系,它们用于处理 searchHistory 的内容,因此我将把 onKeyEvent 函数留在这里。
onTextChange 触发服务器上的字符串搜索,并在 TextInput 的文本为空字符串的情况下关闭 Callout:
private function onTextChange(event:Event):void {
if(searchInput.text=="") {
if(detailSearch.isDropDownOpen) {
(detailSearch.rightView.activeView as RightView).clearDetailList();
detailSearch.isCloseable=true;
}
}
_searchManager.getRicsByChar(searchInput.text);
}
最终服务器将响应并传递一组响应。标注被打开,它的列表中填满了响应。
我不会在此处粘贴所有标注内容的代码,因为它太多了。基本上,用户从任何列表中选择一个项目,Callout 被强制关闭,并且将值传递给组件的搜索功能(尚未在此处粘贴,请耐心等待;)被赋予该项目的值。基本上看起来像这样(别管 FlexGlobals 的东西,一旦焦点问题得到解决,这一切都会被重构):
var search:String = String(event.currentTarget.selectedItem);
FlexGlobals.topLevelApplication.detailSearch.forceClose=true;
FlexGlobals.topLevelApplication.detailSearch.closeDropDown();
FlexGlobals.topLevelApplication.searchEvent(new Array(search), true);
好的,现在是整个功能的最后一步,searchEvent。如前所述,此函数基本上只将格式化的搜索值传递给选定的组件。这要么发生在 TextInput 的“Enter”上(如上面的代码所示),要么发生在从 Callout 列表之一中选择项目时。
public function searchEvent(_searchSymbols:Array, setText:Boolean):void {
if(setText) {
var _searchString:String="";
for each (var _sym:String in _searchSymbols) {
_searchString += _sym + ", ";
}
searchInput.text = _searchString.substring(0, _searchString.length-2);
}
stage.focus=null;
if(selectedWindowContainer) {
// set the array of search items to the selected component here
selectedWindowContainer.setFocus();
} else
trace("[MAIN] no component selected");
}
基本上就是这样。此功能是我的搜索例程的最后一步,所选组件(将获取搜索项)正在获取焦点。 然而,它会再次自动失去焦点,TextInput 将接收它。我不知道这种情况发生在哪里以及为什么会发生,我需要尽快摆脱这种行为!
哇,多么好的帖子,还有人在看这个吗? ;) 好吧,我希望如此。
【问题讨论】:
-
我不完全明白。一些代码,或者可能是截屏视频会在这里有所帮助。 [我也可以自私地说,检查一下 Flextras Mobile AutoComplete ......如果它满足您的需求;与从头开始构建相比,它会为您节省大量时间]
-
我已经查看了您的 AutoComplete 组件,但是它并没有提供我需要的功能。我将编辑第一篇文章以进一步说明这个问题。
-
我仍然认为截图会帮助我(可能还有其他人)理解。 l 听起来你好像有级联列表;其中一个列表是根据第一个中选择的数据填充的。在 Callout 关闭后,您希望关注什么?
-
这正是我所拥有的。我的应用程序中有自定义组件(一个视图上有多个),必须在 Callout 关闭后选择这些组件。当我的例程(在标注中选择项目)完成时,我已经设置了它们的焦点,但最终这些组件(嗯,其中一个)再次失去焦点,因为 TextInput 以某种方式自动获得焦点。
-
我觉得自己像破纪录一样要求更多信息。但是,老实说,我认为代码在这里会有所帮助。如果不查看您的代码,我无法猜测为什么焦点会转移到另一个位置。
标签: actionscript-3 apache-flex mobile flex4 textinput