具有默认移动外观的 Flex TextInput 自动重新获得对标注关闭的关注

发布于 2025-01-07 13:27:43 字数 4074 浏览 0 评论 0原文

我正在为我的 Flex 移动应用程序开发一个简单的自动完成功能。为此,我有一个触发标注的 CalloutButton。 标注包含一些列表,用户可以从中选择项目。在选择项目时,标注将关闭(calloutButton.closeDropDown())。

TextInput 也执行相同的行为。用户输入文本,标注打开,并且根据输入的文本,列表发生变化。到目前为止效果很好。现在,当用户从任何列表中选择一个项目时,标注将关闭。也还好。 现在的问题是,标注关闭后,TextInput 自动重新获得焦点。

在移动设备上,这不仅仅是令人不安的。

我将此行为范围缩小到移动 TextInput 皮肤 (spark.skins.mobile.TextInputSkin),因为没有此皮肤类的 TextInput 不会显示此行为。

现在你可能会说只使用默认皮肤,但不幸的是我不能。 Android 设备的默认皮肤存在一个无法通过 Enter 事件的错误。我可以忍受,因为我不一定依赖于输入事件,但是,即使在打开标注之后,spark 移动皮肤也允许继续在 TextInput 中输入文本,这是迫切需要的,因为列表根据输入的文本。

我无法提供任何代码,因为问题已缩小到 SkinClass,因此不应出现在我自己的代码中。相信我,我尝试了所有好的和不太好的方法来防止 TextInput 再次获得焦点,但没有任何效果。

所以,完全被困在这里了! 希望你们对如何解决这个问题有一些想法。

编辑: 下面是我的应用程序行为的步骤。 (公平地说,标注内的工作流程有点复杂,我在这里使用多个列表和 SplitViewNavigator (因此无法使用 Flextras 自动完成),但这不会影响 TextInput 焦点问题我'我面对)。

  • 在 TextInput 中输入文本
  • 在按键更改时,将打开带有两个列表的标注。
  • 第一个列表根据从 Web 服务输入的文本接收结果
  • 用户从列表中选择项目
  • 第二个列表根据从 Web 服务的第一个列表中的选择接收结果
  • 用户在第二个列表上选择项目
  • 标注关闭

这一切都工作正常,除了 TextInput 在之后接收焦点标注关闭。 我真的不知道是什么触发了这种行为。

Edit2:进一步说明问题的代码。 当然,这被简化为最基本的内容,但它反映了组件和焦点的行为。

首先,CalloutButton 和 TextInput 都可以控制 Callout:

<ui:SearchCallout id="detailSearch"/>

<s:TextInput id="searchInput" skinClass="spark.skins.mobile.TextInputSkin" 
                 enter="historySearch(searchInput.text)" 
                 focusOut="searchFocusOutEvent(event)" 
                 focusIn="searchFocusInEvent(event)"/>

TextInput 的焦点处理程序不执行与 callout 相关的任何操作,它们只是设置另一个组件的当前状态,因此我将把它们留在这里。

函数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”上(如上面的代码所示),要么发生在从标注列表之一中选择一项时。

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 将接收它。我不知道这种情况发生在哪里以及为什么会发生,我需要尽快摆脱这种行为!

哇,多好的帖子啊,还有人在读这篇文章吗? ;) 嗯,我希望如此。

I'm working on a simple auto complete function for my Flex mobile app. For that I've got a CalloutButton that triggers a Callout.
The Callout holds some lists from which the user can select items. On item select, the callout gets closed (calloutButton.closeDropDown()).

The very same behavior is done for a TextInput. The user inputs text, the callout opens and according to the entered text, the lists change. Works fine so far. Now, when the user selects an item from any of the lists, the callout closes. Also fine.
Now the issue, after the callout is closed, the TextInput automatically regains focus.

On a mobile device this is more than disturbing.

I narrowed this behavior down to the mobile TextInput skin (spark.skins.mobile.TextInputSkin) since a TextInput without this skin class doesn't show this behavior.

Now you might say just use the default skin instead but unfortunately I can't. The default skin has a bug with Android devices that doesn't pass though the enter event. That I could live with since I'n not necessarily dependent on the enter event, however, the spark mobile skin allows be to continue entering text in the TextInput even after the callout has been opened, which is desperately needed as the lists change according to the entered text.

I can't provide any code as the problem has been narrowed down to the skinClass, thus should not be in my own code. Believe me, I tried every nice and not so nice method to prevent the TextInput from getting focus again, but nothing worked.

So, totally stuck here!
Hopefully you guys have some ideas on how to solve this.

Edit:
Below the steps of my application's behaviour. (to be fair, the workflow inside the callout is a little more complex, I'm working with several lists and a SplitViewNavigator here (thus can't use the Flextras autocomplete), but that doesn't affect the TextInput focus issue I'm facing).

  • Enter text in TextInput
  • On key change a Callout with two Lists is opened.
  • The first List receives results according to the entered text from a webservice
  • User selects item from list
  • Second list receives results according to selection from first list from webservice
  • User selects item on second list
  • Callout closes

This all works fine, except that the TextInput receives focus after the Callout closes.
I really don't know what triggers this behavior.

Edit2: Code to further illustrate the issue.
Naturally, this is stripped down to the very basics, but it mirrors the behavior of the component and focus.

First the CalloutButton and TextInput that can both control the Callout:

<ui:SearchCallout id="detailSearch"/>

<s:TextInput id="searchInput" skinClass="spark.skins.mobile.TextInputSkin" 
                 enter="historySearch(searchInput.text)" 
                 focusOut="searchFocusOutEvent(event)" 
                 focusIn="searchFocusInEvent(event)"/>

The TextInput's focus handlers don't do anything related to the callout, they just set current states of another component, so I'll leave them out here.

Function historySearch closes the CallOut (I forced it to close as it wouldn't close with the usual closeDropDown()), formats the search text, handles a searchHistory and eventually triggers the search function that passes the formatted search text to the selected component.
Here are the parts that matter for this case:

private function historySearch(val:String):void {

            detailSearch.forceClose=true;
            detailSearch.closeDropDown();

            searchEvent(_searchSyms, true);
}

Note: 'val' (the TextInput's text) is trimmed and whatnot, eventually it will result in an array of strings, represented by '_searchSyms'.

Further eventListeners are as follows:

   searchInput.addEventListener(KeyboardEvent.KEY_DOWN, onKeyEvent);
   searchInput.addEventListener(FlexEvent.VALUE_COMMIT, onKeyEvent);
   searchInput.addEventListener(TextOperationEvent.CHANGE, onTextChange); 

KEY_DOWN and VALUE_COMMIT don't have anything to do with the Callout, they are used to handle stuff for the searchHistory, hence I'll leave the onKeyEvent function out here.

onTextChange triggers the string search on the server and closes the Callout in case the TextInput's text is an empty string:

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);
}

Eventually the server will respond and passes an array of responses. The Callout gets opened and it's lists are filled with the responses.

I won't paste all the Callout content's code here as it would be way too much. Basically, the user selects an item from any of the lists, the Callout is forced to close and the search function that passes the value to the component (not yet pasted here, be patient ;), is given the item's value. That basically looks like this (never mind the FlexGlobals stuff, this gets all refactored once the focus issue has been resolved):

var search:String = String(event.currentTarget.selectedItem);
FlexGlobals.topLevelApplication.detailSearch.forceClose=true;
FlexGlobals.topLevelApplication.detailSearch.closeDropDown();
FlexGlobals.topLevelApplication.searchEvent(new Array(search), true);

Allright, now the final step of the whole functionality, the searchEvent. As already said, this function basically only passes the formatted search value to the selected component. This either happened on 'Enter' of the TextInput (as the code above shows), or on selection of an item from one of the Callout's lists.

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");          
}

And that is basically it. This function is the last step of my search routine, and the selected component (that will get the search items), is getting the focus.
Yet, it automatically loses focus again and the TextInput will receive it. I have no idea where and why this happens, and I need to get rid of this behavior asap!

Wow, what a post, anyone still reading this? ;) Well, I hope so.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅浅 2025-01-14 13:27:43

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

将 TextInput 的 focusEnabled 设置为 false 效果很好,即使焦点指示(TextInput 周围的边框)不再适用于此(我现在可以忍受的问题)。

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

Well, after hours of testing several ways to prevent the TextInput from automatically gaining focus, I (kinda) solved the issue, although I think it's more a dirty hack than anything else.

Setting the TextInput's focusEnabled to false works fine, even though the focus indication (border around the TextInput) won't work with this any more (an issue I can live with for now).

Still, I'd really like to know what exactly is going on here, especially in the mobile skin class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文