具有默认移动设备外观的Flex TextInput会自动重新关注标注关闭

时间:2012-02-20 17:28:49

标签: actionscript-3 flex mobile flex4 textinput

我正在为我的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根据webservice
  • 中输入的文本接收结果
  • 用户从列表中选择项目
  • 第二个列表根据来自webservice的第一个列表中的选择
  • 接收结果
  • 用户选择第二个列表中的项目
  • 标注关闭

这一切都正常,除了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);
}

注意:&#39; val&#39; (TextInput&#39; s文本)被修剪,以及最终它将导致一个字符串数组,由&#39; _searchSyms&#39;表示。

进一步的eventListeners如下:

   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内容的代码,因为它太多了。基本上,用户从任何列表中选择一个项目,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。如前所述,此功能基本上只将格式化的搜索值传递给所选组件。这要么发生在&#39; Enter&#39; of TextInput(如上面的代码所示),或者从其中一个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会收到它。我不知道在哪里以及为什么会发生这种情况,我需要尽快摆脱这种行为!

哇,什么帖子,还有人还在读这个吗? ;)好吧,我希望如此。

1 个答案:

答案 0 :(得分:0)

好吧,经过几个小时的测试来阻止TextInput自动获得焦点,我(有点)解决了这个问题,虽然我认为它比其他任何东西都更糟糕。

将TextInput的focusEnabled设置为false可以正常工作,即使焦点指示(TextInput周围的边框)不再适用于此(我现在可以解决的一个问题)。

不过,我真的很想知道这里到底发生了什么,特别是在移动皮肤课上。