Я пытаюсь реализовать переходы между фрагментами, которые имеют «общие элементы», как описано в новых спецификациях дизайна материалов. Единственный способ, который я могу найти, это ActivityOptionsCompat.makeSceneTransitionAnimation, который, я считаю, работает только с Activity. Я искал эту же функциональность, но с/для фрагментов.Как начать общий переход элементов с помощью фрагментов?
ответ
У меня была такая же проблема, но она работала, добавляя новый фрагмент из другого фрагмента. Следующая страница этого раздела очень полезна для начала работы: https://developer.android.com/training/material/animations.html#Transitions
Следующий мой код, который работает. Я анимация ImageView
от одного фрагмента к другому. Убедитесь, что View
, который вы хотите оживить, имеет одинаковые android:transitionName
в обоих фрагментах. Другое содержание не имеет большого значения.
В качестве теста вы можете скопировать его в оба ваших XML-файла макета. Убедитесь, что изображение существует.
<ImageView
android:transitionName="MyTransition"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/test_image" />
Тогда у меня есть 1 файл в моем res/transition
папку с именем change_image_transform.xml.
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeImageTransform />
</transitionSet>
Теперь вы можете начать. Допустим, у вас есть фрагмент А, содержащий изображение и хотите добавить фрагмент B.
Запустить в Fragment A:
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.product_detail_image_click_area:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));
setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.explode));
// Create new fragment to add (Fragment B)
Fragment fragment = new ImageFragment();
fragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));
fragment.setEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.explode));
// Our shared element (in Fragment A)
mProductImage = (ImageView) mLayout.findViewById(R.id.product_detail_image);
// Add Fragment B
FragmentTransaction ft = getFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack("transaction")
.addSharedElement(mProductImage, "MyTransition");
ft.commit();
}
else {
// Code to run on older devices
}
break;
}
}
Это работает для меня, за исключением того, что он всегда запускает анимацию в верхней части экрана во втором фрагменте. Поэтому, если у меня есть представление в каждом элементе моего списка (или в моем случае RecyclerView), и вы нажимаете на него в нижней части списка, а новое место для этого представления во втором фрагменте находится в нижней части экрана, это фактически анимирует сверху вниз, вместо того, чтобы анимировать из места на экране в первом фрагменте, где началось представление. Кто-нибудь знает, почему это? – brockoli
Я думаю, это потому, что в виде списка многократно содержатся одни и те же элементы. Если вы выполните findViewById, первый элемент вернется. Я думаю, вы должны однозначно идентифицировать анимированный вид, назначая dynamicName динамически при нажатии на элемент. – ar34z
Я назначаю уникальный идентификатор для каждого экземпляра в своем адаптере. Я добавляю позицию позиции. Это, как говорится, я решил свою проблему. Как оказалось, вам нужно включить ChangeTransform в свой TransitionSet. Это указывает системе сохранить начальную позицию выбранного вами вида и использовать это как начальную позицию для анимации в новом фрагменте. – brockoli
Я отправляю это как ответ, так как я новичок здесь и не могу комментировать.
Переходы фрагмента общего элемента do работают с ListViews, если исходное и целевое представления имеют одинаковое (и уникальное) имя перехода.
Если вы сделаете свой список вид адаптера установить уникальные transitionNames мнение, которые вы хотите (например, некоторая константа + конкретный идентификатор элемента) , а также изменить фрагмент детали, чтобы установить то же transitionNames на целевых просмотры во время выполнения (onCreateView), переходы действительно работают!
Это исправлено для меня. Теперь я могу анимировать свои общие ImageViews из одного фрагмента в другой в рамках одной и той же Activity. Теперь моя проблема в том, что мои ImageViews не переводятся на новые позиции, они просто появляются в новом месте, но запускают анимацию масштаба. Я использую setSharedElementEnterTransition (новый ChangeBounds()); когда я создаю экземпляр фрагмента. Аналогичное поведение с ChangeImageTransform() – brockoli
Возможно ли получить часть рабочего кода, чтобы проверить это? Я пробовал какое-то время, и ничего не работает. – FMontano
для меня, даже если каждый из изображений имеет одно и то же имя перехода, он работает. он работает нормально, если изображение все еще находится в памяти и только после первого появления анимации. Уловка, так как я использую загруженные изображения, вы можете сначала просмотреть сводку изображения для резервной, прежде чем загружать правильный. Тем не менее, я должен принудительно загрузить одно и то же изображение в фрагменте B, передав URL-адрес изображения в качестве аргумента из фрагмента A. – takecare
Общие элементы работают с фрагментами, но есть некоторые вещи, которые нужно иметь в виду:
Не пытайтесь установить
sharedElementsTransition
вonCreateView
вашего фрагмента. Вы должны определить их при создании экземпляра вашего фрагмента или вonCreate
.Обратите внимание на официальную документацию о возможных анимациях для переходов ввода/выхода & sharedElementTransition. Они не одинаковы.
проб и ошибок :)
Это должно быть комментарий к принятому ответ, так как я не могу прокомментировать.
Принятый ответ (от WindsurferOak и ar34z) работает, за исключением «незначительной» проблемы, которая вызвала исключение нулевого указателя при навигации с backStack. Кажется, что setSharedElementReturnTransition()
следует вызывать на целевом фрагменте вместо исходного фрагмента.
Таким образом, вместо:
setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));
должно быть
fragment.setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));
Мастов и Мэтт, спасибо за ответ. См. Мое редактирование. –
Ключ использовать пользовательскую транзакцию с
transaction.addSharedElement(sharedElement, "sharedImage");
Shared элемент перехода между двумя фрагментами
В этом примере, один из двух различных ImageViews
следует перевести с ChooserFragment
- DetailFragment
.
В ChooserFragment
макете нам нужны уникальные transitionName
атрибуты:
<ImageView
android:id="@+id/image_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_first"
android:transitionName="fistImage" />
<ImageView
android:id="@+id/image_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_second"
android:transitionName="secondImage" />
В ChooserFragments
классе, нам нужно пройти View
, который щелкнул и идентификатор родительского Activity
которым обрабатывает замена фрагменты (нам нужен идентификатор, чтобы узнать, какой ресурс изображения будет отображаться в DetailFragment
). Как подробно передавать информацию в родительскую деятельность, безусловно, рассматривается в другой документации.
view.findViewById(R.id.image_first).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mCallback != null) {
mCallback.showDetailFragment(view, 1);
}
}
});
view.findViewById(R.id.image_second).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mCallback != null) {
mCallback.showDetailFragment(view, 2);
}
}
});
В DetailFragment
, то ImageView
совместно используемого элемента также нуждается уникальный transitionName
атрибут.
<ImageView
android:id="@+id/image_shared"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:transitionName="sharedImage" />
В onCreateView()
способе DetailFragment
, мы должны решить, какое изображение ресурс должен быть показаны (если мы не делаем этого, общий элемент исчезнет после перехода).
public static DetailFragment newInstance(Bundle args) {
DetailFragment fragment = new DetailFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_detail, container, false);
ImageView sharedImage = (ImageView) view.findViewById(R.id.image_shared);
// Check which resource should be shown.
int type = getArguments().getInt("type");
// Show image based on the type.
switch (type) {
case 1:
sharedImage.setBackgroundResource(R.drawable.ic_first);
break;
case 2:
sharedImage.setBackgroundResource(R.drawable.ic_second);
break;
}
return view;
}
Родитель Activity
является получение обратных вызовов и обрабатывает замену фрагментов.
@Override
public void showDetailFragment(View sharedElement, int type) {
// Get the chooser fragment, which is shown in the moment.
Fragment chooserFragment = getFragmentManager().findFragmentById(R.id.fragment_container);
// Set up the DetailFragment and put the type as argument.
Bundle args = new Bundle();
args.putInt("type", type);
Fragment fragment = DetailFragment.newInstance(args);
// Set up the transaction.
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Define the shared element transition.
fragment.setSharedElementEnterTransition(new DetailsTransition());
fragment.setSharedElementReturnTransition(new DetailsTransition());
// The rest of the views are just fading in/out.
fragment.setEnterTransition(new Fade());
chooserFragment.setExitTransition(new Fade());
// Now use the image's view and the target transitionName to define the shared element.
transaction.addSharedElement(sharedElement, "sharedImage");
// Replace the fragment.
transaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName());
// Enable back navigation with shared element transitions.
transaction.addToBackStack(fragment.getClass().getSimpleName());
// Finally press play.
transaction.commit();
}
Не следует забывать - сама Transition
. Этот пример перемещает и масштабирует общий элемент.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class DetailsTransition extends TransitionSet {
public DetailsTransition() {
setOrdering(ORDERING_TOGETHER);
addTransition(new ChangeBounds()).
addTransition(new ChangeTransform()).
addTransition(new ChangeImageTransform());
}
}
- 1. Почему мой общий переход элементов перестает работать?
- 2. как начать переход Css слева
- 3. Начать переход в VB.NET
- 4. как начать переход с onclick на div?
- 5. Добавить переход транзакции для фрагментов
- 6. sharedElment переход с использованием фрагментов непереход
- 7. общий прослушиватель фрагментов для onBackPress()
- 8. Получить css переход начать с jQuery
- 9. Как начать переход при падении другого div?
- 10. Переход на общий элемент Android
- 11. Сколько уровней активности/фрагментов можно начать?
- 12. Переход по круговым переходам Android для фрагментов
- 13. Как сделать общий, общий, общий переадресацию с помощью htaccess
- 14. Как сделать пользовательский переход с помощью Javascript
- 15. Поиск элементов списка фрагментов адаптера
- 16. как начать анимацию с помощью MVVM?
- 17. Кэширование фрагментов с помощью Touch
- 18. Как организовать приложение с помощью фрагментов?
- 19. Как восстановить заднюю навигацию с помощью фрагментов?
- 20. Начать обслуживание с помощью AlarmManager
- 21. Общий переход между TextView и EditText
- 22. Переключение фрагментов с помощью AsyncTask
- 23. Переход с помощью слайда?
- 24. Как начать работу с Unit Testing? Общий вопрос n00b, мысли?
- 25. Общий список элементов
- 26. Общий класс для элементов списка
- 27. Начать переход CSS3 после просмотра пользователями страницы?
- 28. Остановить анимацию и начать переход при зависании
- 29. Общий переход контента к заголовку (Android)
- 30. Как реализовать переход на Java-переход с помощью flyway-игры
Вы проверили FragmentTransaction.addSharedElement -method; http://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#addSharedElement(android.view.View,java.lang.String)? – harism
Я попытался использовать это на самом деле, но он, похоже, не работал, по крайней мере, из изображения в элементе listview. Вероятно, существует множество недокументированных ограничений. Однако отключение переходов и анимаций в транзакции не помогло. – sbaar
Мне также не удалось заставить его работать с ImageViews внутри элементов списка. Мне удалось собрать очень простое действие с двумя полноэкранными фрагментами. Каждый фрагмент имел 2 вида с черным фоном в разных размерах и положениях, и когда я нажимаю на экран, он переключает фрагмент. В этом случае общие элементы ожидали, как ожидалось. Так что это работает, возможно, нет, когда ваше представление находится в элементе списка. Интересно, это потому, что элементы списка неизвестны до времени выполнения? – brockoli