作者简介:何金源,腾讯Android手Q开发工程师,2011年本科毕业,负责Android手Q无障碍优化工作,对Android无障碍系统原理及开发技术有深入了解。
责编:何永灿 [email protected]
本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅2017年《程序员》
手机应用无障碍化逐渐受到重视,这项技术为盲人或者视力有障碍的人士带来了很大便利。那么对于手机游戏,同样也应该进行无障碍化,本文将以盲人猜地鼠游戏为例,讲解如何对手机游戏进行无障碍化设计,如何让原本无法操作变成可在无障碍模式下正常使用,最后总结手机游戏无障碍化的大体思路。
前言
目前市场上针对盲人进行无障碍化的手机游戏几乎没有,这对于障碍用户来讲,是一大遗憾。实际上,他们对游戏的渴望跟对应用无障碍化的渴望一样强烈,他们也希望能在手机上体验一把游戏的乐趣。下面,我们来探讨手机游戏无障碍化。
由于是首次针对手机游戏进行无障碍化,所以这里挑选了一款较为简单的游戏猜地鼠。猜地鼠是基于MasterMind游戏的玩法(如图1)。原本玩法是两个人对玩,其中一人是出谜者,摆好不同颜色的球的位置;另一个人是猜谜者,每个回合猜各个位置应该放什么颜色的球。每回合结束后会有结果提示。
图1 MasterMind游戏
而猜地鼠则是会有不同颜色的地鼠,用户每个回合要猜地鼠的颜色排列顺序。这是使用Cocos2d-x引擎开发的,引擎并没对无障碍模式做出优化,所以游戏开发完成后只有一个大焦点在界面上,当用户点击这个焦点时,没法进行下一步操作,怎么点也进不了游戏界面。如图2所示。
图2 优化前的游戏界面
构造无障碍虚拟节点
Cocos2d-x引擎是支持跨平台的,所以我们可以针对不同平台区分处理无障碍。首先看下Android平台,在游戏中,Cocos2d-x是把游戏里的界面、图片和文字等素材画到GLSurfaceView上,而GLSurfaceView是添加到Cocos2dxActivity的布局中。Cocos2dxActivity是Cocos2d-x引擎在Android平台上最主要的Activity,我们要对游戏进行无障碍化,就需要让这个Activity支持无障碍。
在Android平台,可以对自定义View进行无障碍化支持。具体的原理可以参考官网上的介绍,或者《程序员》8月发布的《Android无障碍宝典》。所以我们第一步,就是为Cocos2dxActivity增加一个自定义View。
public class MasterMind extends Cocos2dxActivity{
private AccessibilityGameView mGameView;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Rect rectangle = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);
AccessibilityHelper.setScreen(rectangle.width(), rectangle.height());
@SuppressWarnings("deprecation")
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
getWindowManager().getDefaultDisplay().getWidth(),
getWindowManager().getDefaultDisplay().getHeight());
mGameView = new AccessibilityGameView(this);
addContentView(mGameView, params);
AccessibilityHelper.setGameView(mGameView);
ViewCompat.setImportantForAccessibility(mGLSurfaceView, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
static {
System.loadLibrary("game");
}
}
AccessibilityGameView是个简单透明的自定义View,直接通过addContentView方法加入到布局中,同时把GLSurfaceView设置为不需无障碍焦点。
public class AccessibilityGameView extends View {
private BaseSceneHelper mTouchHelper;
public AccessibilityGameView(Context context) {
super(context);
}
public void setCurSceneHelper(BaseSceneHelper helper){
mTouchHelper = helper;
}
@SuppressLint("NewApi")
@Override
protected boolean dispatchHoverEvent(MotionEvent event) {
if(mTouchHelper != null |