为什么我的标签栏会破坏我的AndEngine活动?

时间:2012-02-11 14:43:48

标签: android andengine

我的Android应用程序有一个标签栏,使用Intent在每个标签中启动内容,就像在Android的API Demos example中一样。我在其中一个标签下放了一个AndEngine活动。我的第一个问题是:这是一个合理的想法吗?或者,如果我使用AndEngine,在AndEngine中实现我的应用程序的整个UI是否更好?

假设我还没有进入非首发,我遇到的具体问题如下。这个AndEngine活动 - 我在基于选项卡的应用程序中加入的活动 - 是AndEngine PinchZoom example的简化版本。它可以很好地工作,直到您从标签切换然后再返回。此时,视图重新出现,但您无法再滚动或缩放。

这是我的活动课程。如果您想查看标签栏类,请告诉我。正如您所看到的,当用户离开选项卡时,我尝试关闭各种侦听器和检测器,并在返回时将其重新打开。但是我已经使用断点确定了在返回选项卡后触摸屏幕时未调用onSceneTouchEvent。有什么干预和捕捉我的触摸事件?或者是否存在一些不活跃的东西需要恢复生机?

我在AndEngine论坛上也提到了posted这个问题。

修改

感谢您的建议,Guillaume。你是对的,当用户返回标签时不会调用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);
    }
}

2 个答案:

答案 0 :(得分:2)

使用断点进行调试时,您的onResumeGame方法是否被调用?

也许您需要在基本setOnSceneTouchListener(this)中设置初始化(特别是onResume)?或者您也可以尝试在onCreateScene中添加它。

答案 1 :(得分:2)

托米: 我在自己的应用程序中有相同的场景,我需要三个选项卡,其中一个是andEngine。但是我发现TabActivity没有以与触发新Intent相同的方式重新初始化选项卡。如果你记录其他一个标签的生命周期,你会发现这不仅仅是一个动态的东西,而是一个TabActivity的东西。 关于这个问题,这里有一个非常有用的主题: http://groups.google.com/group/android-developers/browse_thread/thread/d89f1d5f913bb6f7

包括将每个标签设置为单个活动中的视图的示例。链接在这里。我使用了commonsware myeslf中的代码,发现他们的库和示例经过了充分的测试和高质量的测试。 https://github.com/commonsguy/cw-android/tree/master/Fancy/Tab/

无论如何,在没有重新编写Andengine核心类的情况下,我找不到一种方法来制作一个tabactivity工作,这超出了我在项目中可以做的范围。

所以我做的解决方法就是: 我自己构建标签作为三个共享页脚的活动,让您在它们之间进行交换。我不得不在历史记录中徘徊,并在适当的时候覆盖后退按钮的行为以保持在标签内。 另外,我在Android清单中使用了一个意图标志:

android:launchMode="singleInstance"

通过确保只创建了一个Andengine选项卡实例,帮助应用程序顺利运行。

希望这会有所帮助。如果andengine可以与TabActivity兼容,那将会很棒,但我认为此时并不完全。