【发布时间】:2012-02-11 14:43:47
【问题描述】:
我的 Android 应用有一个标签栏,它使用 Intent 来启动每个标签中的内容,如 Android 的 API Demos example 中所示。我在其中一个选项卡下放置了一个 AndEngine 活动。我的第一个问题是:这是一个合理的想法吗?或者,如果我使用的是 AndEngine,在 AndEngine 中实现我的应用的整个 UI 是否更好?
假设我还没有入门,我遇到的具体问题如下。这个 AndEngine 活动——我在我的基于标签的应用程序中加入的活动——是 AndEngine PinchZoom example 的简化版本。在您切换离开选项卡然后再返回之前,它运行良好。此时,视图会重新出现,但您无法再滚动或缩放。
这是我的活动课。如果您也想查看标签栏类,请告诉我。如您所见,我尝试在用户离开选项卡时关闭各种侦听器和检测器,并在它们返回时重新打开它们。但是我已经使用断点建立了 onSceneTouchEvent 在返回选项卡后触摸屏幕时不会被调用。有什么东西在干预和捕捉我的触摸事件吗?还是有什么东西变得不活跃,需要恢复活力?
我也在 AndEngine 论坛上posted了这个问题。
编辑:
感谢您的建议,纪尧姆。没错,当用户返回选项卡时,不会调用 onResumeGame。我以为我已经检查过了,但我一定是把可滚动图形一次放在两个选项卡下弄糊涂了。此时会调用 onResume 方法,而不会调用 onCreateGame。因此,我更改了代码,以便在onResume 中打开触摸检测器。这个方法肯定会在我想要的时候被调用,所以我想这是一个进步,但是当我返回标签后触摸屏幕时,onSceneTouchEvent 仍然没有被触发。更新后的代码如下,更改标记为// NEW。
public class HomeActivity extends SimpleBaseGameActivity implements IOnSceneTouchListener,
IScrollDetectorListener, IPinchZoomDetectorListener {
private static final int CAMERA_WIDTH = 480;
private static final int CAMERA_HEIGHT = 628;
private boolean mInitialised = false; // NEW
private Scene mScene;
private ZoomCamera mZoomCamera;
private ITexture mTexture;
private ITextureRegion mGrassTextureRegion;
private SurfaceScrollDetector mScrollDetector;
private PinchZoomDetector mPinchZoomDetector;
private float mPinchZoomStartedCameraZoomFactor;
@Override
public EngineOptions onCreateEngineOptions() {
this.mZoomCamera = new ZoomCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
final EngineOptions engineOptions = new EngineOptions(true,
ScreenOrientation.PORTRAIT_FIXED,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mZoomCamera);
if (MultiTouch.isSupported(this)) {
if (MultiTouch.isSupportedDistinct(this)) {
Toast.makeText(this, "MultiTouch detected.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(
this,
"MultiTouch detected, but your device has problems distinguishing between "
+ "fingers.", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(this, "Sorry your device does NOT support MultiTouch!",
Toast.LENGTH_LONG).show();
}
return engineOptions;
}
@Override
public void onCreateResources() {
try {
this.mTexture = new BitmapTexture() {
@Override
protected InputStream onGetInputStream() throws IOException {
return getAssets().open("gfx/background_grass.png");
}
}.load(this.getTextureManager());
this.mGrassTextureRegion = TextureRegionFactory.extractFromTexture(mTexture);
} catch (IOException e) {
Debug.e(e);
}
}
@Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
this.mScene = new Scene();
this.mScene.setOnAreaTouchTraversalFrontToBack();
this.mScene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
// Calculate the coordinates for the sprite, so it's centered on the
// camera.
final float centerX = (CAMERA_WIDTH - this.mGrassTextureRegion.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mGrassTextureRegion.getHeight()) / 2;
// Create the sprite and add it to the scene.
final Sprite grass = new Sprite(centerX, centerY, this.mGrassTextureRegion,
this.getVertexBufferObjectManager());
this.mScene.attachChild(grass);
enableTouchDetectors(); // NEW
mInitialised = true; // NEW
return this.mScene;
}
@Override
public void onPause() {
this.mScene.setTouchAreaBindingOnActionDownEnabled(false);
this.mScene.setOnSceneTouchListener(null);
this.mPinchZoomDetector = null;
this.mScrollDetector = null;
super.onPause();
}
// NEW method
@Override
public void onResume() {
super.onResume();
// If returning to the tab, switch the touch detectors back on.
if (mInitialised) {
enableTouchDetectors();
}
}
// This method has been removed since Guillaume's answer.
// @Override
// public void onResumeGame() {
// super.onResumeGame();
// this.mScrollDetector = new SurfaceScrollDetector(this);
// this.mPinchZoomDetector = new PinchZoomDetector(this);
// this.mScene.setOnSceneTouchListener(this);
// this.mScene.setTouchAreaBindingOnActionDownEnabled(true);
// }
@Override
public void onScrollStarted(final ScrollDetector pScollDetector, final int pPointerID,
final float pDistanceX, final float pDistanceY) {
}
@Override
public void onScroll(final ScrollDetector pScollDetector, final int pPointerID,
final float pDistanceX, final float pDistanceY) {
final float zoomFactor = this.mZoomCamera.getZoomFactor();
this.mZoomCamera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
}
@Override
public void onScrollFinished(final ScrollDetector pScollDetector, final int pPointerID,
final float pDistanceX, final float pDistanceY) {
}
@Override
public void onPinchZoomStarted(final PinchZoomDetector pPinchZoomDetector,
final TouchEvent pTouchEvent) {
this.mPinchZoomStartedCameraZoomFactor = this.mZoomCamera.getZoomFactor();
}
@Override
public void onPinchZoom(final PinchZoomDetector pPinchZoomDetector,
final TouchEvent pTouchEvent, final float pZoomFactor) {
this.mZoomCamera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor * pZoomFactor);
}
@Override
public void onPinchZoomFinished(final PinchZoomDetector pPinchZoomDetector,
final TouchEvent pTouchEvent, final float pZoomFactor) {
}
@Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
this.mPinchZoomDetector.onTouchEvent(pSceneTouchEvent);
if (this.mPinchZoomDetector.isZooming()) {
this.mScrollDetector.setEnabled(false);
} else {
if (pSceneTouchEvent.isActionDown()) {
this.mScrollDetector.setEnabled(true);
}
this.mScrollDetector.onTouchEvent(pSceneTouchEvent);
}
return true;
}
// NEW method
private void enableTouchDetectors() {
this.mScrollDetector = new SurfaceScrollDetector(this);
this.mPinchZoomDetector = new PinchZoomDetector(this);
this.mScene.setOnSceneTouchListener(this);
this.mScene.setTouchAreaBindingOnActionDownEnabled(true);
}
}
【问题讨论】:
-
在您的代码第一次运行时,enableTouchDetectors 被调用了两次,但不需要。
-
我刚刚签入了调试器,它只被调用了一次。也许你的错误是假设 onResume 是在 onCreateScene 之后调用的,而实际上它是在之前调用的。