5

flex 选项卡的顺序对于可用性(显而易见)和可访问性(它定义了屏幕阅读器的阅读顺序)都很重要。然而,Flex 3.5 似乎几乎没有支持影响它以适应更复杂的应用程序。

据我目前所知:

  • 选项卡排序由 mx.managers.FocusManager 计算,它负责整个应用程序的一个“选项卡循环”(即,不是每个容器都有一个,而是整个应用程序都有一个)。嵌入的 .swf 文件和弹出窗口是个例外,它们都有自己的 FocusManager。

  • FocusManager 内部的逻辑被标记为私有,并且类在 Application.initialize() 中实例化,因此很难改变行为(缺少重写部分 SDK,可能会造成许可证问题)

  • 制表符排序查找每个组件的 tabIndex (int) 属性。所有具有此属性集 (>0) 的组件都按其值排序,否则使用视觉层次结构(使用容器嵌套和容器内的子顺序)。

  • 所有没有 tabIndex 的组件都被排序在设置它的组件之后(在内部,“tabIndex not set”映射到“tabIndex = int.MAX_VALUE)

  • 具有相同 tabIndex 的两个组件按视觉层次结构排序。

这意味着您可以使用视觉层次结构的自动排序(主要是您想要的),或者您可以直接使用指定 tabIndexes - 但是如果您这样做,您会完全搞砸自动排序。如果您使用自定义组件并想要更改其中的选项卡顺序,这尤其糟糕:一旦您这样做,您就破坏了使用您的组件的所有屏幕的选项卡顺序。此外,您不能只在最高级别的 mxml 文件上设置选项卡顺序,因为您通常无权访问您使用的组件的内部工作。

例子:

accVerticalStuff.mxml

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Label text="One"/>
    <mx:TextInput tabIndex="1" id="One" />

    <mx:Label text="Two" />
    <mx:TextInput tabIndex="2" id="Two"/>

    <mx:Label text="Three" />
    <mx:TextInput tabIndex="3" id="Three"/>

</mx:VBox>

应用程序.mxml

预期结果:标签顺序将首先是左侧的三个垂直项目,然后是右侧的三个垂直项目,即按容器分组。TopLevelElement 是 Tab 键顺序中的第一个。(如果没有指定 tabIndex,它完全以这种方式工作,但是我们无法将 tabIndex 实际更改为例如切换一和三,无论出于何种原因我们可能想要这样做)

实际结果: tab 排序是水平的,即在两个输入表单之间跳转。TopLevelElement(未指定 tabIndex)在 Tab 键顺序中位于最后。

更改容器的嵌套在模块化项目中不起作用,更改子项的顺序会影响它们的显示位置(而使用 Canvas 容器会丢失 AutoLayout)。

有没有办法(可能很复杂,但最好不要重写 SDK)来指定单个组件的制表符顺序,而不依赖于其他组件?

如果一切都失败了,升级到 Flex4 是否有助于解决这个问题?

4

2 回答 2

7

经过一番研究,我发现了以下内容:

  • 如果(即使是单个)DisplayObject具有tabIndex > 0这意味着从现在开始按下TAB只会在实例之间切换焦点tabIndex > 0
  • 如果只有一个实例,tabIndex > 0它将永远集中
  • 如果current.tabIndex - next.tabIndex > 1没关系,tabIndex 将增加到下一个现有值
  • 如果多个实例具有相同的 tabIndex 值,它们将以本机顺序接收焦点(好像从未定义过 tabIndex)
    --------------- -------------------------------------------------- ——

    所以:

  • 用于在某些 DisplayObjects 之间设置 TAB 导航(无论它们位于显示列表中的哪个位置) - 只需tabIndex > 0为它们中的每一个设置。

  • 用于从 TAB 列表中删除实例 - 设置tabIndex = 0(但如果应用程序中只有 DisplayObjectstabIndex == 0左侧 - TAB 将在它们之间自然切换焦点)。tabEnabled = false应该是更好的选择
  • 为了在每个组内创建具有自然 TAB 顺序的多组 DisplayObject,同时保持组之间的特定顺序 - 为每个组选择一个 tabIndex(首先出现小值)并将您选择的 tabIndex 应用于组的每个成员。

    我认为 TAB 列表中的太多实例无用且烦人,因此管理它的最佳方法应该是使其等于当前应用程序状态的前 10 个最有用的 UI 元素的列表。

和一些代码(基于您的示例):
showclasses.NewFile.mxml:

<mx:VBox xmlns:mx="library://ns.adobe.com/flex/mx"
         xmlns:fx="http://ns.adobe.com/mxml/2009" data="1,2,3" creationComplete="addFocuses();">
    <fx:Script>
        <![CDATA[       
        private function addFocuses():void{
            var focs:Array = data.split(',');
            One.tabIndex = focs[0];
            Two.tabIndex = focs[1];
            Three.tabIndex = focs[2];           
        }       
        ]]>
    </fx:Script>
    <mx:Label text="One"/>
    <mx:TextInput id="One" />
    <mx:Label text="Two" />
    <mx:TextInput id="Two"/>
    <mx:Label text="Three" />
    <mx:TextInput id="Three"/>
</mx:VBox>

主要.mxml:

<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:th="showclasses.*">
    <mx:HBox>
        <th:NewFile data="1,2,3" />
        <th:NewFile data="1,2,3" />
        <th:NewFile data="1,2,3" />
    </mx:HBox>
</mx:Application>

如果数据值为 1、2、3;1,2,3; 1,2,3 - 焦点从左到右水平移动(自然是因为每行内的 tabIndex 是恒定的),然后向下切换到下一行的左侧元素。
如果他们是 2; 空,3;0,null,1 (null == 0 for tabIndex) - 焦点将出现在右下角,然后出现在左上角,最后出现在中心。
希望这会有用

于 2010-12-14T12:13:39.450 回答
1

我认为 www0z0k 提供的某些信息不再准确(或者可能从未准确过?)只需阅读有关tabIndex财产的 Flex Docs:

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html#tabIndex

指定 SWF 文件中对象的制表符顺序。tabIndex 属性默认为 -1,这意味着没有为对象设置选项卡索引。

如果 SWF 文件中当前显示的任何对象包含 tabIndex 属性,则会禁用自动 Tab 键排序,并且 Tab 键排序是根据 SWF 文件中对象的 tabIndex 属性计算的。自定义选项卡排序仅包括具有 tabIndex 属性的对象。

tabIndex 属性可以是非负整数。对象根据它们的 tabIndex 属性按升序排列。tabIndex 值为 1 的对象位于 tabIndex 值为 2 的对象之前。不要对多个对象使用相同的 tabIndex 值。

tabIndex 属性定义的自定义选项卡顺序是平面的。这意味着不关注 SWF 文件中对象的层次关系。SWF 文件中具有 tabIndex 属性的所有对象都按 Tab 键顺序放置,并且 Tab 键顺序由 tabIndex 值的顺序决定。

编辑:根据我使用 Flex 3.3.0 的经验,www0z0k 提出的断言 #1 和 #2 是错误的。对于 #1,您未明确设置 tabIndex 的控件将始终位于您按 Tab 键顺序赋予正数的所有控件之前。对于 #2,它遵循并且可以观察到,如果您只设置一个 tabIndex,那么一个控件将按照 tab 顺序跟随所有其他自动控件。

于 2011-08-17T16:06:13.230 回答