如何更改 Flex 中的选项卡顺序(Actionscript、SDK 3.5)
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
经过一番研究后,我发现了以下内容:
DisplayObject
有tabIndex > 0
意味着从现在开始按TAB
只会在tabIndex > 0 的实例之间切换焦点。 0
tabIndex > 的实例 它将永远聚焦
current.tabIndex - next.tabIndex > , 1
没关系,tabIndex 将增加到下一个现有值如果多个实例具有相同的 tabIndex 值,它们将以本机顺序接收焦点(就像从未定义 tabIndex 一样)
-------------------------------------------------- --------------------------------------
所以:
要在某些 DisplayObject 之间设置 TAB 导航(无论它们位于显示列表中的哪个位置),只需设置
tabIndex > 即可。 0
即可。tabIndex = 0
(但如果只有 DisplayObjects 具有tabIndex == 0
> 在应用程序中左侧 - TAB 将在它们之间自然地切换焦点)。tabEnabled = false
应该是一个更好的选择我认为 TAB 列表中的太多实例是无用且烦人的,因此管理它的最佳方法应该是使其等于当前应用程序状态的前 10 个最有用的 UI 元素的列表。
还有一点一些代码(基于您的示例):
showclasses.NewFile.mxml:
Main.mxml:
如果数据值为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:
DisplayObject
hastabIndex > 0
it means that from now pressingTAB
will only switcth focus between instances withtabIndex > 0
tabIndex > 0
it will be focused forevercurrent.tabIndex - next.tabIndex > 1
it doesn't matter, tabIndex will increase to the next existing valueif 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.tabIndex = 0
(but if there are only DisplayObjects withtabIndex == 0
left in the app - TAB will switch focus naturally between them).tabEnabled = false
should be a better choicei 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:
Main.mxml:
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
我认为 www0z0k 提供的一些信息不再准确(或者可能从来都不是?)只需阅读
tabIndex
属性上的 Flex 文档:http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/ InteractiveObject.html#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
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.