|
当用户按下能够引起我们的项目接收焦点的导航键时(通常是箭头键),就调用定制项目的traverse() 方法。如果方法返回true,那么用户下次按下导航键时,还会调用这个方法,循环往复,直到方法返回false为止。
传递给traverse()方法的第一个参数,是造成焦点转移到我们项目的按键。参数值是Canvas类中定义的方向性游戏动作(game actions)中的一个:Canvas.UP, Canvas.DOWN, Canvas.LEFT,和 Canvas.RIGHT,或者为空值CustomItem.NONE。如果值为NONE, 那么一些与平台相关的事件,例如改变窗体大小,会使项目获得焦点。
剩下的参数负责描述屏幕的尺寸和项目在屏幕上的可见区域。某些项目,特别是是那些显示大量文本的项目,比屏幕的尺寸大,它们必须能够响应游历事件,滚动它们的可视内容。traverse()方法的文档详细解释了这些参数,但是您现在没有必要考虑它们。
如果您想让项目对用户的按键响应仍然保留焦点,那么您的实现就应当返回true。在CustomItem中的实现总返回false, 这样形成了与StringItem的行为类似的行为:按下任何导航键,都会把焦点转移到不同的项目。这个行为对于CustomItem的大多数简单子类都合适。
更具交互性的项目可能需要覆盖traverse()方法来定制导航键的行为。一个比较好的例子是Gauge项目,在某些实现里,按下右键和左键可以增减组件里的值。当值达到最大或最小值时,traverse()方法返回false,允许按键把焦点移动到与按键方向对应的下一个组件上。文本字段的某些实现工作也来也类似,
把插入点向左或向右移动,只在插入点到达字段的开始或结束时才转移焦点。
对于OutlineItem,上、下方向键按照常规把焦点转移到另一个组件。因为没有插入点需要考虑——所有的编辑都在另外一个屏幕处理——OutlineItem 把右键和左键解释为缩进或凸出文本。在没有水平方向键的设备上,outliner MIDlet会显示额外的菜单项,表示缩进文本或凸出文本,就象我稍后说明的那样。
下面是traverse的实现:
<%@ control language="c#" autoeventwireup="true" codefile="webusercontrol2.ascx.cs" inherits="webusercontrol2" %> /**
* 用来在可能的时候缩进项目或凸出项目。
*/
protected boolean traverse(
int dir,
int viewportWidth,
int viewportHeight,
int[] visRect_inout )
{
// 用这个标记来区分焦点是
// 游历进本项目,还是
// 在本项目内游历:
if ( traversingItem != this )
{
// 游历进:标记自己,返回 true
traversingItem = this;
return true;
}
// 处理在本项目内的游历
switch ( dir )
{
case Canvas.RIGHT:
if ( isIndentable() )
{
indent();
}
repaint();
return true;
case Canvas.LEFT:
if ( isOutdentable() )
{
outdent();
}
repaint();
return true;
case NONE:
// 什么都不做:只是重绘窗体布局
return true;
default:
// 退出
}
return false;
} |
请注意:当焦点游历进您的项目时,就会调用traverse()方法,只要您的实现返回true,那么每次焦点都是在您的项目内游历。您应当在代码中区分这些情况。OutlineItem保持了一个静态引用,用它来判断项目是否由于这次调用traverse()而获得焦点。如果是这样,它就返回true ,这样它就可以接收下一个方向键。
对于接下来针对traverse()的调用, OutlineItem查看按下了哪个键。如果按下的是右键或左键,它就修改缩进级别。在NONE的情况下,OutlineItem什么也不做,但是返回true,以便重新获得焦点。对于剩下的二种情况,上和下,则返回false ,允许焦点游历到下一个或上一个项目。
因为改变缩进级别也会改变项目的可视外观,所以traverse()方法调用repaint()方法,告诉窗体重绘它自己。因为OutlineItem没有做文字环绕,所以项目的期望尺寸不会变化。如果尺寸发生了变化,traverse()方法应用调用invalidate() ,而不是调用repaint(),好让窗体重新安排它的布局。
调整用户交互
对于新增的灵活性,MIDP 2.0让您可以把命令和窗体上的单独项目关联。当项目拥有焦点时,项目的命令就会和窗体的命令组合在一起,形成上下文敏感的菜单。响应项目菜单的命令,不需要付出比响应窗体的更多的努力;它不过是另外一个接口。Outliner实现了ItemCommandListener接口,把自己加为窗体中每个项目的监听器。
向项目加入命令或删除命令的方式,按照您期望的方式进行:只需调用addCommand()方法和removeCommand() 方法。因为每个OutlineItem都会跟踪自己的状态——它是展开的还是的,它是缩进的、凸出的,是上移还是下移——每个定制项目都管理着自己的适用命令列表。每当一个OutlineItem 的状态变化时,项目都会调用自己的updateCommands()命令。
<%@ control language="c#" autoeventwireup="true" codefile="webusercontrol2.ascx.cs" inherits="webusercontrol2" %>private void updateCommands()
{
if ( !hasPointerPress() )
{
removeCommand( expandCommand );
removeCommand( collapseCommand );
// 进入展开或折叠的命令
if ( isCollapsed() )
addCommand( expandCommand );
else
addCommand( collapseCommand );
}
if ( !hasHorizontalTraversal() )
{
removeCommand( indentCommand );
removeCommand( outdentCommand );
// 进入缩进、凸出的命令
if ( isIndentable() )
addCommand( indentCommand );
if ( isOutdentable() )
addCommand( outdentCommand );
}
removeCommand( upCommand );
removeCommand( downCommand );
if ( canMoveUp() )
addCommand( upCommand );
if ( canMoveDown() )
addCommand( downCommand );
removeCommand( deleteCommand );
if ( getIndex() > 0 )
{
// 如果不为根
addCommand( deleteCommand );
}
}
|
|