Общие сведения о переходах общих элементов exit/reenter

Я занимаюсь некоторыми рудиментарными исследованиями переходов общих элементов в Android L. Простой пример, который я установил, имеет представление изображения, переводимое с верхней части экрана в нижнюю часть экрана во время переходов активности, и я расширил продолжительность перехода, поэтому я могу видеть, как все работает. На данный момент я столкнулся с двумя проблемами, пытаясь понять, как работают Shared Element Transitions.

1) При использовании только переходов Enter/Return (Exit/Reenter установлено значение null). Переход ввода прекрасен, но когда нажата кнопка "Назад", вид анимации на какое-то время останавливается, а затем снова появляется в конечной позиции. Похоже на этот вопрос, но я установил все переходы Exist/Reenter в null, поэтому не знаю, почему это происходит.

2) При использовании только переходов Exit/Reenter (Enter/Return установлено значение null). Ничего не происходит, представление переходит по экрану, как и его последующий переход по умолчанию (длительность 300 мс), а при нажатии назад изображение возвращается в исходное положение.

Как использовать переходы Exit/Reenter?

Вот мой код:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@drawable/ic_launcher"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Animate!"
        android:id="@+id/button"
        android:layout_centerVertical="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>

activity_second.xml

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageView2"
    android:src="@drawable/ic_launcher"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" />

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        getWindow().setAllowEnterTransitionOverlap(false);
        getWindow().setAllowReturnTransitionOverlap(false);


        getWindow().setSharedElementExitTransition(exitTransition());
        getWindow().setSharedElementReenterTransition(reenterTransition());
        //getWindow().setSharedElementExitTransition(null);
        //getWindow().setSharedElementReenterTransition(null);


        setContentView(R.layout.activity_main);

        final View iView = findViewById(R.id.imageView);
        iView.setTransitionName("image");

        final Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                ActivityOptions options = ActivityOptions
                        .makeSceneTransitionAnimation(MainActivity.this, iView, "image");
                startActivity(intent, options.toBundle());
            }
        });
    }

    private Transition exitTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setInterpolator(new BounceInterpolator());
        bounds.setDuration(2000);

        return bounds;
    }

    private Transition reenterTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setInterpolator(new OvershootInterpolator());
        bounds.setDuration(2000);

        return bounds;
    }
}

SecondActivity.java

public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        getWindow().setAllowEnterTransitionOverlap(false);
        getWindow().setAllowReturnTransitionOverlap(false);


        //getWindow().setSharedElementEnterTransition(enterTransition());
        //getWindow().setSharedElementReturnTransition(returnTransition());
        getWindow().setSharedElementEnterTransition(null);
        getWindow().setSharedElementReturnTransition(null);


        setContentView(R.layout.activity_second);

        final View iView = findViewById(R.id.imageView2);
        iView.setTransitionName("image");
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finishAfterTransition();
    }

    private Transition enterTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setDuration(2000);

        return bounds;
    }

    private Transition returnTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setInterpolator(new DecelerateInterpolator());
        bounds.setDuration(2000);

        return bounds;
    }
}

Ответы

Ответ 1

Как я помню, в L есть ошибка, которая приводит к прерыванию перехода возврата общего элемента, если оно занимает больше времени, чем длительность перехода повторного входа. Если вы измените продолжительность перехода на повторный вход (в вызывающей активности), это должно устранить проблему прерывания до тех пор, пока ошибка не будет исправлена ​​в MR1.

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

Ответ 2

  • Вы не должны называть finishAfterTransition() в onBackPressed(). Суперкласс Activity уже сделает это за вас.

  • Вы должны позвонить requestFeature() до super.onCreate(). Запрос Window.FEATURE_ACTIVITY_TRANSITIONS не нужен, если вы используете тему Theme.Material (или аналогичную).

  • Вызов setAllowEnterTransitionOverlap(false) и setAllowReturnTransitionOverlap(false) здесь лишний. Они определяют переходы содержимого содержимого окна приложения... они вообще не влияют на переходы содержимого содержимого элемента.

  • Настройка перехода к переходу и повторного входа в общий элемент редко необходима. Вы почти всегда хотите использовать переходы ввода и возврата. Если вы установите только переходы общего доступа и повторно присоедините общие элементы и оставьте значения вхождения и возврата общих элементов равными null, вызываемая активность не будет иметь никакого способа узнать, как оживить общие элементы при начале перехода, и анимация окажется сломанной.