【问题标题】:Flex TextInput with default mobile skins automatically regains focus on callout close具有默认移动皮肤的 Flex TextInput 会自动重新关注标注关闭
【发布时间】: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


【解决方案1】:

好吧,经过数小时测试防止 TextInput 自动获得焦点的几种方法后,我(有点)解决了这个问题,尽管我认为这比其他任何事情都更肮脏。

将 TextInput 的 focusEnabled 设置为 false 可以正常工作,即使焦点指示(TextInput 周围的边框)不再适用(这是我现在可以忍受的问题)。

不过,我真的很想知道这里到底发生了什么,尤其是在移动皮肤类中。

【讨论】:

  • 确实为我们的旧 Flex 应用程序提供了一点服务,但又遇到了这个问题。感谢上帝提供像 Feathers 这样的框架。抛弃这个垃圾(Flex 移动)并转向真正有效的东西是非常明智的决定。