如何更改 Flex 中的选项卡顺序(Actionscript、SDK 3.5)

发布于 2024-10-07 01:23:45 字数 1755 浏览 0 评论 0原文

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

据我目前所知:

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

  • FocusManager 内部的逻辑被标记为私有,并且该类在 Application.initialize() 中实例化,因此更改行为并不容易(除非重写部分 SDK,这可能会带来许可问题)

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

  • 所有没有 tabIndex 的组件都排序在设置了 tabIndex 的组件之后(在内部,“tabIndex 未设置”映射到“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>

Application.mxml

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

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

更改容器的嵌套在模块化项目中不起作用,并且更改子级的顺序会影响其显示位置(而使用 Canvas 容器会失去自动布局)。

有没有一种方法(可能很复杂,但最好不需要重写 SDK)来指定单个组件的 Tab 顺序,独立于其他组件?

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

The flex tab ordering is important both for usability (obvious) and accessibility (it defines the screen readers read ordering). However, Flex 3.5 seems to have next to no support to influence it for more complicated applications.

From what I know so far:

  • the tab ordering is calculated by the mx.managers.FocusManager, which takes care of one "tab cycle" for the entire application (i.e. there is not one for each container, but one for the whole app). The exception being embedded .swf files and popups, each of which have their own FocusManager.

  • the logic inside the FocusManager is marked as private, and the class is instantiated in Application.initialize(), so it's not easy to change the behaviour (short of rewriting parts of the SDK, which might pose license trouble)

  • The tab ordering looks for each components tabIndex (int) property. All components which have this property set (>0) are ordered by its value, otherwise the visual hierarchy is used (which uses container nesting and child order inside the containers).

  • All components without tabIndex are sorted to be after the components which have it set (internally, "tabIndex not set" is mapped to "tabIndex = int.MAX_VALUE)

  • two components with the same tabIndex are ordered by visual hierarchy.

This means that you can either use the automatic ordering by visual hierarchy (mostly what you want) OR you can use specifying tabIndexes directly - BUT if you do this you completely screw the automatic ordering. This is especially bad if you work with custom components and want to change the tab ordering inside those: once you do this, you ruined the tab order for all screens using your component. Also you cannot just set the tab ordering only on the highest level mxml file, as often you don't have access to the inner workings of the components you use.

Example:

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>

Application.mxml

Expected Result: the tab order would be first the three vertical items on the left, then the three vertical items on the right, i.e. grouped by the containers. The TopLevelElement is the first in the tab order.
(it works exactly in this way if no tabIndex is specified, however then we're not able to actuall change the tabIndex to e.g. switch One and Three for whatever reasons we might want to do so)

Actual Result: the tab ordering is horizontal, i.e. jumping between the two input forms. The TopLevelElement (w/o tabIndex specified) is last in the tab order.

Changing the nesting of containers will not work in modularized projects, and changing the ordering of childs would affect their display position (whereas going for Canvas container looses the AutoLayout).

Is there a way (possibly complicated, but preferably short of rewriting the SDK) to specify the tab ordering for single components, independently of other components?

if all else fails, would upgrading to Flex4 help in solving this issue?

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

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

发布评论

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

评论(2

久光 2024-10-14 01:23:45

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

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

    所以:

  • 要在某些 DisplayObject 之间设置 TAB 导航(无论它们位于显示列表中的哪个位置),只需设置 tabIndex > 即可。 0 即可。

  • 用于从 TAB 列表中删除实例 - 设置 tabIndex = 0 (但如果只有 DisplayObjects 具有 tabIndex == 0 > 在应用程序中左侧 - TAB 将在它们之间自然地切换焦点)。 tabEnabled = false 应该是一个更好的选择
  • 用于创建多组 DisplayObjects,每组内具有自然的 TAB 顺序,同时保持组之间的特定顺序 - 为每组选择一个 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>

Main.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(tabIndex 为 null == 0) - 焦点将出现在右下角,然后出现在左上角,最后出现在中心。
希望这会有用

after a little research i found out the following:

  • if (even a single) DisplayObject has tabIndex > 0 it means that from now pressing TAB will only switcth focus between instances with tabIndex > 0
  • if there's only one instance with tabIndex > 0 it will be focused forever
  • if current.tabIndex - next.tabIndex > 1 it doesn't matter, tabIndex will increase to the next existing value
  • if several instances have equal tabIndex values they will recieve focus in a native order (as if tabIndex is never defined)
    -------------------------------------------------------------------------------

    so:

  • for setting up TAB navigation between some DisplayObjects (no matter where're they located in the display list) - just set tabIndex > 0 for every of them.

  • for removing an instance from TAB list - set tabIndex = 0 (but if there are only DisplayObjects with tabIndex == 0 left in the app - TAB will switch focus naturally between them). tabEnabled = false should be a better choice
  • for creating several groups of DisplayObjects with natural TAB order inside each one while keeping certain order between the groups - select one tabIndex for each group (small values appear first) and apply the tabIndex you selected to every member of a group.

    i think that too much instances in the TAB list are useless and annoying so the best way to manage it should be making it equal to list of top e.g. 10 most useful UI elements for current app state.

and a little bit of code (based on your example):
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>

Main.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>

if data values are 1,2,3; 1,2,3; 1,2,3 - focus moves horizontally from left to right (naturally because tabIndex is constant inside each row) and then switches to the left element of the next row down.
if they are 2; null,3; 0,null,1 (null == 0 for tabIndex) - focus will appear in the lower-right corner then in the upper-left and at last in the center.
hope this'll be useful

夏の忆 2024-10-14 01:23:45

我认为 www0z0k 提供的一些信息不再准确(或者可能从来都不是?)只需阅读 tabIndex 属性上的 Flex 文档:

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

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

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

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

tabIndex 属性定义的自定义 Tab 键顺序是固定的。
这意味着不关注层级关系
SWF 文件中的对象的数量。 SWF 文件中带有 tabIndex 的所有对象
属性按 Tab 键顺序放置,并且 Tab 键顺序为
由 tabIndex 值的顺序确定。

编辑:根据我使用 Flex 3.3.0 的经验,www0z0k 的断言 #1 和 #2 是错误的。对于#1,未显式设置 tabIndex 的控件将始终位于按 Tab 键顺序为其指定正数的所有控件之前。对于#2,可以观察到,如果您仅设置一个 tabIndex,则该控件将按照 Tab 键顺序跟随所有其他自动控件。

I think some of the info www0z0k gives is no longer accurate (or maybe never was?) Just read the Flex Docs on tabIndex property:

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

Specifies the tab ordering of objects in a SWF file. The tabIndex
property is -1 by default, meaning no tab index is set for the object.

If any currently displayed object in the SWF file contains a tabIndex
property, automatic tab ordering is disabled, and the tab ordering is
calculated from the tabIndex properties of objects in the SWF file.
The custom tab ordering includes only objects that have tabIndex
properties.

The tabIndex property can be a non-negative integer. The objects are
ordered according to their tabIndex properties, in ascending order. An
object with a tabIndex value of 1 precedes an object with a tabIndex
value of 2. Do not use the same tabIndex value for multiple objects.

The custom tab ordering that the tabIndex property defines is flat.
This means that no attention is paid to the hierarchical relationships
of objects in the SWF file. All objects in the SWF file with tabIndex
properties are placed in the tab order, and the tab order is
determined by the order of the tabIndex values.

Edit: In my experience with Flex 3.3.0, assertion #1 and #2 made by www0z0k are wrong. For #1, the controls that you don't explicitly set tabIndex on will just always fall before all the controls you give positive numbers to in the tab order. For #2, it then follows and is observable that if you set just one tabIndex, that one control will just follow all other automatic controls in the tab order.

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