具有默认移动皮肤的 Flex TextInput 会自动重新关注标注关闭

Posted

技术标签:

【中文标题】具有默认移动皮肤的 Flex TextInput 会自动重新关注标注关闭【英文标题】:Flex TextInput with default mobile skins automatically regains focus on callout close 【发布时间】:2012-03-11 01:20:30 【问题描述】:

我正在为我的 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 以某种方式自动获得焦点。 我觉得自己像破纪录一样要求更多信息。但是,老实说,我认为代码在这里会有所帮助。如果不查看您的代码,我无法猜测为什么焦点会转移到另一个位置。 【参考方案1】:

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

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

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

【讨论】:

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

以上是关于具有默认移动皮肤的 Flex TextInput 会自动重新关注标注关闭的主要内容,如果未能解决你的问题,请参考以下文章

为不可编辑的 textinput 和 textarea flex 组件设置样式

Flex TextArea 自动完成,而不是 TextInput

Flex Mobile textInput 滚动文本滞后

Flex 按钮皮肤恢复默认设置

Flex 4.6 AIR 3.2 TextInput 工件

Flex TextInput 控件:搜索样式渲染