5

Androidで新しい KitKat Transitions API を使用しています。2 つのレイアウトを使用して 2つのSceneオブジェクトを作成しました。Scene 1からへとアニメーション化しScene 2ますFragmentSceneユーザーが戻るボタンを押したときに、自動的に前に戻りたい。

を使用する場合、何らかの組み込みのバックスタック メカニズムはありTransitionsますか?

を呼び出すのは簡単ですが、アニメーションを持つすべてのフラグメントにリスナーTransitionManager.go(scene1)を実装したくありません。onBackPressed()Scene

4

2 に答える 2

1

私は自分のソリューションを展開することになりました。

Activityこれを実装してください

public interface SceneBackstackHandler {

    public void addBackstackListener(BackstackListener listener);

    public void removeBackstackListener(BackstackListener listener);

    public void removeAllBackstackListeners();

    public interface BackstackListener {
        public boolean onBackPressed();
    }
}

アクティビティ

private final Object mBackstackListenerLock = new Object();
private List<BackstackListener> mBackstackListeners = new ArrayList<>();

@Override
public void onBackPressed() {
    synchronized (mBackstackListenerLock) {
        for (BackstackListener mBackstackListener : mBackstackListeners) {
            if (mBackstackListener.onBackPressed()) {
                // handled by fragment
                return;
            }
        }
        super.onBackPressed();
    }
}

@Override
protected void onPause() {
    super.onPause();
    removeAllBackstackListeners();
}

@Override
public void addBackstackListener(BackstackListener listener) {
    synchronized (mBackstackListenerLock) {
        mBackstackListeners.add(listener);
    }
}

@Override
public void removeBackstackListener(BackstackListener listener) {
    synchronized (mBackstackListenerLock) {
        mBackstackListeners.remove(listener);
    }
}

@Override
public void removeAllBackstackListeners() {
    synchronized (mBackstackListenerLock) {
        mBackstackListeners.clear();
    }
}

子フラグメント:

public class MySceneFragment extends Fragment
        implements SceneBackstackHandler.BackstackListener {

    private Scene mCurrentScene;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mBackstackHandler = (SceneBackstackHandler) activity;
        mBackstackHandler.addBackstackListener(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mBackstackHandler.removeBackstackListener(this);
    }

    @Override
    public boolean onBackPressed() {
        if (mCurrentScene != null && mCurrentScene.equals(mMyScene)) {
            removeMyScene();
            return true;
        }
        return false;
    }

    private void changeScene(Scene scene) {
        TransitionManager.go(scene);
        mCurrentScene = scene;
    }
}
于 2014-09-17T23:38:04.847 に答える
1

Otto イベント バスを使用して、Activityとの間で通信しFragmentます。コントロールActivityは独自Stackのカスタム back イベントを維持します。各イベントには back action が含まれますRunnable。つまり、back ボタンが押されたときに実行されるアクションです。

このアプローチの利点は、設計がわずかに分離されていることであり、より多くのフラグメントに合わせて拡張する必要があります。読みやすくするために、ここでは Otto イベントを my 内に定義しましたFragmentが、これらはプロジェクト内の別の場所に簡単に移動できます。

これがどのように行われるかを理解するためのサンプルコードです。

フラグメント

Fragmentは、Otto イベント バスにaをポストし、イベントがカスタム スタックからポップされたときに実行されるアクションを提供することによって、次のバック プレスを取得する意図を通知します。Fragment がデタッチされると、 バスに を送信して、アクティビティのカスタム スタックから の back アクションをすべて削除します。BackStackRequestEventRunnableActivityClearBackStackEventFragment

public class MyFragment extends Fragment {

    private final String BACK_STACK_ID = "MY_FRAGMENT";

    ...

    public class BackStackRequestEvent {
        private Runnable action;
        private String id;

        public BackStackRequestEvent(Runnable action, String id) {
            this.action = action;
            this.id = id;
        }

        public void goBack() {
            action.run();
        }

        public String getId() {
            return id;
        }
    }

    public class ClearBackStackEvent {
        private String id;

        public ClearBackStackEvent(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }
    }

    ...

    @Override
    public void onDetach() {
        super.onDetach();
        // Get your Otto singleton and notify Activity that this
        // Fragment's back actions are no longer needed
        // The Fragment lifecycle stage in which you do this might vary
        // based on your needs
        EventBus.getInstance().post(new ClearBackStackEvent(BACK_STACK_ID));
    }

    ...

    public void someChangeInFragment() {
        // Notify the Activity that we want to intercept the next onBackPressed
        EventBus.getInstance().post(new BackStackRequestEvent(new Runnable()
        {
            @Override
            public void run() {
                // Reverse what we did
                doBackAction();
            }
        }, BACK_STACK_ID)); // constant used later to remove items from Stack
    }
}

アクティビティ

アクティビティは、上でおよびで定義したイベントへの関心を登録/登録解除します。new を受け取ると、それをカスタム バック スタックに追加します。が呼び出されると、バック スタックをポップし、フラグメントの. スタックに何もない場合は、通常のバック動作に従います。onStart()onStop()BackStackRequestEventonBackPressed()BackStackRequestEvent.goBack()Runnable

フラグメントがデタッチされると、アクティビティは を受け取り、提供された のすべてのアイテムをスタックからClearBackStackEvent削除します。id

public class MyActivity extends Activity {

    private Stack<MyFragment.BackStackRequestEvent> customBackStack = new Stack<>();

    ...

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getInstance().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getInstance().unregister(this);
    }

    @Subscribe // Annotation indicating that we want to intercept this Otto event
    public void backStackRequested(MyFragment.BackStackRequestEvent request) {
        customBackStack.push(request);
    }

    @Override
    public void onBackPressed() {
        if (customBackStack.empty()) {
            // No custom actions so default behaviour followed
            super.onBackPressed();
        }
        else {
            // Pop the custom action and call its goBack() action
            MyFragment.BackStackRequestEvent back = customBackStack.pop();
            back.goBack();
        }
    }

    @Subscribe
    public void clearBackStackRequested(MyFragment.ClearBackStackEvent request) {
        String id = request.getId();
        for (MyFragment.BackStackRequestEvent backItem : customBackStack) {
            if (backItem.getId().contentEquals(id)) {
                customBackStack.remove(backItem);
            }
        }
    }
}
于 2015-11-23T12:19:31.860 に答える