Как я могу предотвратить отображение строки состояния и панели навигации во время перехода анимации сцены активности?
Во-первых, мой статус-бэнд установлен на темно-коричневый, а мой фон на панели навигации по умолчанию черный. Я использую тему Material light.
Я начинаю новое действие с помощью ActivityOptions.makeSceneTransitionAnimation
с переходом по умолчанию, и я замечаю, что и статусные, и навигационные полосы кратковременно исчезают до белого, а затем возвращаются к правильным цветам.
В соответствии с документацией:
Чтобы получить полный эффект перехода, вы должны включить переходы содержимого окна как для вызывающего, так и для вызываемого. В противном случае вызывающая активность начнет переход с выхода, но тогда вы увидите переход на окно (например, масштабирование или исчезновение)
Я использую getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
как для вызывающего, так и для вызываемого.
Аналогично, если я изменил переход ввода на слайд, на панели состояния и навигации на короткое время будет переход слайдов на белом фоне.
Как предотвратить отображение строки состояния и навигационной панели во время перехода анимации сцены активности?
Ответы
Ответ 1
Есть два подхода, которые вы можете использовать, о которых я знаю, для предотвращения анимации навигации/строки состояния во время перехода:
Подход №1: исключить строку состояния и панель навигации из окна по умолчанию для выхода/перехода в режим затухания
Причина того, что панель навигации/состояния затухает и исчезает во время перехода, заключается в том, что по умолчанию все неотображаемые представления (в том числе фоны навигации/состояния) будут постепенно исчезать/находиться в ваших вызываемых/вызываемых действиях соответственно переход начинается. Тем не менее, вы можете легко обойти это, исключив фоны навигации/строки состояния из окна перехода по умолчанию по умолчанию/введите Fade
. Просто добавьте следующий код в методы вашей деятельности onCreate()
:
Transition fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);
getWindow().setExitTransition(fade);
getWindow().setEnterTransition(fade);
Этот переход также может быть объявлен в теме активности с использованием XML (т.е. в вашем собственном файле res/transition/window_fade.xml
):
<?xml version="1.0" encoding="utf-8"?>
<fade xmlns:android="http://schemas.android.com/apk/res/android">
<targets>
<target android:excludeId="@android:id/statusBarBackground"/>
<target android:excludeId="@android:id/navigationBarBackground"/>
</targets>
</fade>
Подход №2: добавить строку состояния и панель навигации в качестве общих элементов
Этот подход основывается на ответе klmprt, который почти работал у меня... хотя мне все еще нужно было сделать пару модификаций.
В моей деятельности по вызову я использовал следующий код для запуска Activity:
View statusBar = findViewById(android.R.id.statusBarBackground);
View navigationBar = findViewById(android.R.id.navigationBarBackground);
List<Pair<View, String>> pairs = new ArrayList<>();
if (statusBar != null) {
pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME));
}
if (navigationBar != null) {
pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME));
}
pairs.add(Pair.create(mSharedElement, mSharedElement.getTransitionName()));
Bundle options = ActivityOptions.makeSceneTransitionAnimation(activity,
pairs.toArray(new Pair[pairs.size()])).toBundle();
startActivity(new Intent(context, NextActivity.class), options);
До сих пор это по существу то же самое, что и предложенный в его ответе klmprt. Однако мне также необходимо добавить следующий код в мой метод Activity onCreate()
, чтобы предотвратить "мигание" строки состояния и навигационной панели во время перехода:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
// Postpone the transition until the window decor view has
// finished its layout.
postponeEnterTransition();
final View decor = getWindow().getDecorView();
decor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
decor.getViewTreeObserver().removeOnPreDrawListener(this);
startPostponedEnterTransition();
return true;
}
});
}
Добавление строки состояния и фона навигационных панелей в качестве общих элементов заставит их рисовать поверх окна по умолчанию для выхода/перехода в режим затухания, что означает, что они не будут исчезать во время перехода. Дополнительную информацию об этом подходе можно найти в этот пост в Google+.
Ответ 2
Вам нужно поделиться ими в ActivityOptions.makeSceneTransitionAnimation.
например:
ActivityOptions.makeSceneTransitionAnimation(... Pair.create(activity.findViewById(android.R.id.window_status_bar), Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME)
(извините psuedo, у меня нет точного значения android.R.id)
Вы можете выполнить соответствующий переход, разделив представления.
Ответ 3
Полностью запретить переходы Activity переходить на общие переходы элементов:
В завершающей операции вызовите getWindow(). setExitTransition (null);
В процессе ввода вызовите getWindow(). setEnterTransition (null);
Из fooobar.com/questions/57417/...
Я подозреваю, что это может иметь побочные эффекты, но не знаю точно. Это мертво просто и работает, хотя.
Предотвращение мигания определенных элементов:
Я начал с ответа Алекс Локвуд и сделал несколько экспериментов, чтобы попытаться заставить его работать. Ядро его правильно, хотя мне не нужен код, который он предлагает для принимающей операции, но я столкнулся с некоторыми проблемами, вызвав его в фрагменте (вместо Activity) и установив панель инструментов в качестве панели действий.
О, Фрагмент? Я видел много комментариев, что попытка получить ссылки на строку состояния и панель навигации была нулевой. То же самое произошло со мной, пока я не понял, что не найду их в макете Фрагмента... они были выше этого уровня. Следовательно, код ниже, чтобы получить представление декора из Activity и выполнить поиск. Тогда я нашел их без проблем.
В конце концов, я разработал этот метод утилиты:
public static Bundle transitionOptions(Activity activity, int transitionViewResId, int transitionNameResId) {
if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
return null;
}
View decorView = activity.getWindow().getDecorView();
View statusBar = decorView.findViewById(android.R.id.statusBarBackground);
View navigationBar = decorView.findViewById(android.R.id.navigationBarBackground);
View appBarLayout = decorView.findViewById(**R.id.appbarlayout**);
View transitionView = decorView.findViewById(transitionViewResId);
String transitionName = activity.getString(transitionNameResId);
List<Pair<View, String>> pairs = new ArrayList<>();
pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME));
pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME));
if (appBarLayout != null) {
pairs.add(Pair.create(appBarLayout, activity.getString(**R.string.transition_appbarlayout**)));
}
pairs.add(Pair.create(transitionView, transitionName));
//noinspection unchecked - we're not worried about the "unchecked" conversion of List<Pair> to Pair[] here
return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs.toArray(new Pair[pairs.size()]))
.toBundle();
}
Примечание R.string.transition_appbarlayout и R.id.appbarlayout. Эти идентификаторы являются произвольными, если они соответствуют тому, что использует ваш код. В моем XML я компоную пользовательскую панель действий так (отредактирован до сути):
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:id="**@+id/appbarlayout**"
android:transitionName="**@string/transition_appbarlayout**">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"/>
</android.support.design.widget.AppBarLayout>
Если вы не используете такую панель инструментов, эту часть можно удалить из утилиты.
Затем вы бы назвали его в своем фрагменте следующим образом:
startActivity(intent, UIUtils.transitionOptions(getActivity(),
R.id.**my_view**,
R.string.**transition_my_view**));
Использование любых значений, которые вы хотите, до тех пор, пока они соответствуют вашему XML.
Это предотвращает мигание строки состояния, панели инструментов и панели навигации (кнопки "назад/домой/последние приложения" ) во время перехода. Остальная часть перехода активности является нормальной.
В моем случае наша тема приложения имеет android:windowBackground
синего цвета. Это вызывает синюю вспышку при переходе, что довольно сложно. Но вместо того, чтобы делать изменения, которые влияют на все приложение, подобное этому, на данный момент я перехожу к первому, быстрому и грязному варианту.
Ответ 4
Насколько я понимаю, это вызвано перекрытием переходов. Чтобы преодолеть эту проблему, я использовал следующие значения в методах onCreate()
для обоих видов деятельности:
getWindow().setAllowEnterTransitionOverlap(false);
getWindow().setAllowReturnTransitionOverlap(false);
Ответ 5
Вот как я это сделал. Я разделяю как Status Bar
, так и Navigation Bar
в SharedElementTransition
вместе с ImageView
:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
View imageView = view.findViewById(R.id.iv);
Resources resources = view.getResources();
imageView.setTransitionName(resources.getString(R.string.transition_image_thumbnail));
Pair<View, String> p1 = Pair.create(imageView, resources.getString(R.string.transition_image_thumbnail));
Window window = getActivity().getWindow();
View navigationBar = getActivity().findViewById(android.R.id.navigationBarBackground);
View statusBar = getActivity().findViewById(android.R.id.statusBarBackground);
Pair<View, String> p2 = Pair.create(statusBar, statusBar.getTransitionName());
Pair<View, String> p3 = Pair.create(navigationBar, navigationBar.getTransitionName());
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
p1, p2, p3);
ActivityCompat.startActivity(getActivity(), intent, options.toBundle());
} else {
startActivity(intent);
}
Ответ 6
getWindow().setEnterTransition(null);
на входе Ввод удалил белый оверлей для меня.