Transitions-Everywhere
Transitions-Everywhere copied to clipboard
Alpha version Activity transition
Доброго времени суток. Я попробовал сделать реализацию Transition между Activity на основе вашей библиотеки. Это в принципе более-менее рабочая версия. Просто хотелось бы услышать ваше мнение о такой реализации. Суть в том, что мы указываем view содержащий элементы которые нужно анимировать (если не указать берется content). У этой view мы получаем все элементы имеющие id, берем у них параметры нужные для анимации и засовываем все это в Intent. Запускаем новое Activity. На новом Activity на основе пришедших данных формируется FrameLayout. В setContentView мы вставляем этот FrameLayout, создаем сцену для Layout который по идее должен располагаться на этом Activity и вызываем ChangeScene для нее. С обратным Transition все немного сложнее. При вызове onBackPressed опять создаем FrameLayout на основе пришедших данных, затем находим все элементы из этих данных на текущем экране, берем важные для данного типа view данные (к примеру для ImageView это drawable) и вставляем в наши элементы на FrameLayout. На основе этого FrameLayout формируем сцену и вызываем changeScene.
Еще нужно добавить какой-либо listener по завершению Transition, потому что сейчас завершение Activity делается с помощью postDelayed c отсрочкой равной длительности анимации, это кривой подход и бывает Activity завершается раньше, чем закончилась анимация.
Приветствую! Идея и реализация довольно неплохая. Можно пытаться развить идею. Во первых, про listener по завершению Transition. Это сделать не сложно, у Transition есть addListener и можно подписаться на колбек onTransitionEnd. Во вторых, я бы вот в какую сторону двигался. Нам при открытии второго активити на самом деле нет смысла прям восстанавливать и выстраивать сцены. Переход от сцены к сцене внутри состоит из снятия нужных для конкретной Transition стартовых параметров, сохранения их в TransitionValues, смены лэйаутов, снятия этих же параметров в финальной сцене и анимированного применения этих изменений. То есть по идее мы должны снять начальные параметры ещё находясь в первой активити, запустить вторую активити, применить новый лэйаут, снять финальные параметры и запустить анимацию. без лишних действий. единственное что нужно дописать, это каким то образом передать информацию во вторую активити о вьюшках, которые были в первой активити, отсутствуют во второй активити и которые необходимо анимировать. чтобы восстановить эти вьюхи и запустить их анимированное пропадание. Это наверно можно сделать дописав captureStartValues у Visibility transition. Сохранять "скриншот" вьюшки в bitmap и передавая его во вторую активити.
А почему в качестве координат объекта для аминирования, берутся его координаты внутри его контейнера, а не относительно всего экрана? Просто получается, что у объекта анимации на первой сцене, контейнер должен быть точно таким же как на второй сцене. Иначе анимация будет глючить.
Речь идет вероятно о ChangeBounds. Изначально в андроиде он задумывался как анимирующий изменения внутри одного и того же Parent. Потом ему добавили метод setReparent (по умолчанию выключен), в который если проставить true ChangeBounds будет брать координаты как раз относительно всего экрана, а не контейнера. Правда он уже помечен deprecated, потому что в андроид добавили дополнительный транзишн ChangeMatrixTransform, который может помочь отдельно санимировать эту разницу между в координатах parent из первой сцены и из второй сцены. но ChangeMatrixTransform у меня пока так и не получилось бекпортнуть, поэтому пока лучше этот setReparent использовать. То есть тебе сейчас как раз этот режим пригодится по идее
Я наверное уже заколебал, но все таки) У меня наконец-то появилось время и я решил сделать как вы и предлагали ("То есть по идее мы должны снять начальные параметры ещё находясь в первой активити, запустить вторую активити, применить новый лэйаут, снять финальные параметры и запустить анимацию."). Собственно с открытием активити никаких проблем нет. А вот с обратной анимацией есть проблемы. Я пошел по самому простому пути и для обратной анимации просто меняю местами mStartValues, mEndValues у Transition который я использовал для анимации открытия. Для того, что бы срабатывало скрывание вьюхи на время анимации я дополнительно меняю местами ссылки на вьюху у стартовых значений и конечных. И тут возникает проблема с теми вьюхами которые есть на этом экране и нет на предыдущем (те которые добавляются в addUnmatched()). Получается, что сама вьюха остается на месте плюс появляется ее анимированная копия.
И вот вроде проблем быть не должно. И я не понимаю из-за чего такой эффект возник.
И еще одна проблема в том, что у Animator нет аналога setFillAfter у Animation. И вот что-то я не смог найти просто способа застыть вьюхи после выполнения анимации. Из-за этого получается моргание на несколько долей секунды. Конечно можно действительно поменять положение у анимируемых вьюх, но может вы знаете способ получше? А то гугление мне не помогло.
извиняюсь, что так долго отвечал. конечно не заколебал) мне тоже интересно получится ли удобно использовать библиотеку для активити. про первое: почему так происходит. потому что сама суть таких транзишнов, которые анимируют изменения видимости заключается в том, что вьюшка раньше была, а теперь её нет. и мы анимируем её пропадание. то есть сам транзишн вьюшку не прячет, она уже пропала. а в нашем кейсе она не пропала, так что тут её вручную придется прятать. можно просто setVisibility(View.INVISIBLE) выставить. чтобы отличить такие вью от остальных можно воспользоваться getVisibilityChangeInfo() класса Visibility. про второе суть та же, на самом деле. ChangeBounds двигает на самом деле не саму вьюшку, а её скриншот, и делает она так как раз потому что включен у ChangeBounds reparentMode. зачем так сделали в андроиде изначально: видимо чтобы если конечный parent меньше в размерах, чтобы уметь анимировать вьюшку вне контейнера parentа. и на самом деле тут не проблема Animator и аналога setFillAfter. тот эффект происходит изза того, что в ChangeBounds написано anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { ViewOverlayUtils.removeOverlay(sceneRoot, drawable); ViewUtils.setTransitionAlpha(view, transitionAlpha); } }); то есть прячет скриншот и показывает реальную вьюшку, потому что знает что эта вьюшка и должна быть там, куда он скриншот подвинул. а у нас не так получилось. как эту проблему решить я сходу тоже не могу придумать, подумаю ещё.
Ну вроде предыдущие проблемы я поправил. Не очень красиво сделал, но все же. Я в Transition добавил boolean переменную isReverse. И если она true, то немного корректирую поведение Transition пот нужды обратной анимации. Сделал я это под Visibility и ChangeBounds. Вроде они хорошо отрабатывают. Ну и пока появилось время, я решил начать делать исчезновение тех View которых нет на этом экране. Вы советовали "Это наверно можно сделать дописав captureStartValues у Visibility transition. Сохранять "скриншот" вьюшки в bitmap и передавая его во вторую активити". Я добавил. Прилепил Fade к моему transition иии нечто странное стало происходить. Fade действует абсолютно на все View. Чудеса. Происходящее очень похоже на то как в фильме Матрица, агенты уклонялись от пуль... То есть... Блин... это очень странно выглядит. Хотя в общем и целом они конечно исчезают. В связи с этим вопрос: можно как то сказать, что "на те view на которые уже зацеплен какой-то Transition - не вешать новых? А, ну еще эта сволочь не работает в обратную сторону(
Короче сохранять скриншот вьюшки в bitmap, что бы после ухода с текущего экрана анимировать появление тех вьюх, что нет на текущем экране - не вариант. Память съедается в нереальных количествах.
да, непростая штука. надо пытаться смотреть как в официальных Android Transitions это все обошли. почему фейд применяется ко всем вьюшкам - видимо потому что оно считает что и те вью, которые типа "перебегают", на самом деле мы анимируем не те самые финальные вьюшки, а их скриншоты с прошлого экрана.