Почему панель вкладок нарушает мою активность в AndEngine? - PullRequest
3 голосов
/ 11 февраля 2012

В моем Android-приложении есть панель вкладок, в которой для запуска контента на каждой вкладке используется Намерение, как в демонстрациях API Android , пример . Я поместил действие AndEngine под одну из вкладок. Мой первый вопрос: это разумная идея? Или, если я использую AndEngine, лучше ли реализовать весь пользовательский интерфейс моего приложения в AndEngine?

Предполагая, что я еще не начинаю, конкретная проблема, с которой я столкнулся, заключается в следующем. Это действие AndEngine, которое я включил в свое приложение на основе вкладок, представляет собой упрощенную версию AndEngine PinchZoom пример . Это работает хорошо, пока вы не переключитесь с вкладки, а затем снова вернетесь. В этот момент вид снова появляется, но вы больше не можете прокручивать или масштабировать.

Вот мой класс деятельности. Дайте мне знать, если вы хотите увидеть класс панели вкладок тоже. Как вы можете видеть, я пытался отключить различные прослушиватели и детекторы, когда пользователь покидает вкладку, и включить их снова, когда они вернутся. Но я установил, используя точку останова, что onSceneTouchEvent не вызывается, когда я касаюсь экрана после возврата на вкладку. Что-то вмешивается и захватывает мои сенсорные события? Или есть что-то, что становится неактивным и нуждается в возвращении к жизни?

Я также разместил этот вопрос на форумах AndEngine.

Edit:

Спасибо за ваши предложения, Гийом. Вы правы, что 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 ]

2 голосов
/ 15 февраля 2012

Томми: У меня был такой же сценарий в моем собственном приложении, в котором мне нужно было три вкладки с одним существом и двигателем.Но я обнаружил, что TabActivity не выполняет повторную инициализацию вкладок так же, как это делает запуск нового намерения.Если вы зарегистрируете жизненный цикл одной из ваших других вкладок, то увидите, что это не просто вещь, связанная с движением, но и функция 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, что выходило за рамки того, что я мог сделать в проекте.

Итак, в качестве обходного пути я сделал следующее: я сам строю вкладки как три действия, которые имеют общий нижний колонтитул, позволяющий переключаться между ними.Мне пришлось немного поэкспериментировать с историей и переопределить поведение кнопки «Назад», чтобы при необходимости оставаться на вкладках.Кроме того, я использовал флаг намерения в манифесте Android:

android:launchMode="singleInstance"

, который помог приложению работать гладко, гарантируя, что когда-либо был создан только один экземпляр вкладки Andengine.

Надеюсь, это поможет.Было бы замечательно, если бы andengine можно было совместить с TabActivity, но я не думаю, что это полностью в данный момент.

2 голосов
/ 13 февраля 2012

При отладке с использованием точки останова вызывается ли ваш метод onResumeGame?

Может быть, вам нужно установить инициализации (в частности, setOnSceneTouchListener(this)) в базовом onResume? Или вы можете попробовать добавить его в onCreateScene.

...