Fresco: Общий переход элемента

Созданный на 28 мар. 2015  ·  57Комментарии  ·  Источник: facebook/fresco

Переход к общим элементам не работает.

Проверено на устройстве Motorola с Android 5.0

Самый полезный комментарий

Вот обходной путь, который я использую, и он отлично работает:
https://github.com/bumptech/glide

Все 57 Комментарий

Вы можете дать нам более подробную информацию? Что именно вы пытались сделать и что произошло вместо этого?

В новой версии Android, lollipop, мы можем использовать ImageView в качестве общего перехода элемента между действиями. В этом случае изображение будет плавно переходить от одного действия к другому. При использовании SimpleDraweeView он просто исчезает.

Код для проверки должен быть примерно таким:

тема приложения:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
    </style>

Activity1 Layout.xml:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/image"
        android:layout_width="@dimen/size_1"
        android:layout_height="@dimen/size_1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"/>

</RelativeLayout>

Activity2 Layout.xml:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/image"
        android:layout_width="@dimen/size_2"
        android:layout_height="@dimen/size_2"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:transitionName="image_transition"/>

</RelativeLayout>

Код для запуска второго действия:

    Intent intent = new Intent(activity1, Activity2.class);
    ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(activity1, simpleDraweeView1, "image_transition");
    activity1.startActivity(intent, options.toBundle());

Этот код должен выполнять переход между действиями, в которых изображение перемещается и изменяет размер из левого верхнего угла действия 1 в правый нижний угол действия 2. Я протестировал аналогичный код, загружающий изображения из сети, и он не отображается. анимация.

Думаю, это тоже реально https://github.com/facebook/fresco/issues/99

Я подозреваю, что это связано с событиями присоединения / отсоединения, которые view получает при переходе. Мы должны это исследовать.

Это я тоже могу подтвердить. Кажется, что переходы общих элементов на Fresco не работают. Было бы здорово, если бы мы могли исправить это, поскольку это очень важная функция в будущем.

Со мной тоже было. При установке атрибута transtitionName xml в SimpleDraweeView метод setImageUri () перестал работать

Есть обновления по этому поводу?

После того, как FadeDrawable завершил анимацию реального изображения, появляется журнал:
com.facebook.samples.comparison D / ViewRootImpl ﹕ changeCanvasOpacity: opaque = false

возможно, из-за измененияCanvasOpacity изображение не отрисовывается.

Исправлена ​​ошибка? Это очень важно и для моего проекта. :)

пакет org.goodev.droidddle.drawee;

import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.view.SimpleDraweeView;

import android.content.Context;
import android.graphics.Matrix;
import android.util.AttributeSet;

открытый класс TranslateDraweeView расширяет SimpleDraweeView {
public TranslateDraweeView (контекстный контекст) {
супер (контекст);
}

public TranslateDraweeView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public TranslateDraweeView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public TranslateDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
    super(context, hierarchy);
}

// looks like overwrite this method can fix this issue
// but still don't figure out why
public void animateTransform(Matrix matrix) {
    invalidate();
}

}

@goodev нет такого метода перезаписи.

@ shumin0809 просто добавьте этот метод, это

Я вижу другое, но все еще ошибочное поведение с SharedElementTransitions. Не знаю, та же ли это, связанная или отдельная проблема.

_Воспроизведение _
Довольно стандартная настройка для SharedElementTransition:

  • RecyclerView во фрагменте с GridLayoutManager, отображающим множество изображений как SimpleDraweeViews, динамически устанавливая для них transitionName в методе привязки держателя просмотра (где я также устанавливаю uri)
  • OnClick запускает переход к другому фрагменту с одним представлением SimpleDrawee и тем же именем перехода, также устанавливаемым динамически

_Ожидается _
Что касается обычных ImageView (при условии совпадения scaleType), бесшовная анимация общего ресурса между фрагментами

_Обсуждается _
SharedElementTransition возникает, но перед появлением целевого изображения наблюдается мерцание (кажется, что целевое изображение не установлено достаточно рано)

_Примечания _
Я пробовал загружать изображения из Интернета и с диска, и изображение загружается и находится в кеше перед запуском перехода. Код целевого фрагмента извлекает точно такой же uri. Я возился, пытаясь использовать конвейер напрямую (и многому научился), но не смог повлиять на результат.

_Настройка _
Устройства: Nexus 5 и Nexus 7 (2013 г.), оба работают под управлением Android 5.1.1 (API 22).
Обновленная библиотека и инструменты: fresco (0.5.0), Android Studio (1.3 Preview 3 EAP.0), compileSdk (22), инструменты сборки (22.0.1)

_Реализации _
Во время написания этого поста я заметил 2 вещи, которые могут иметь отношение к делу:

  • Два Drawees _ имеют_ разные размеры (это не проблема для перехода на стандартные ImageView, и я ничего не помню о предварительной выборке, которая устанавливает целевые размеры)
  • По памяти я думаю, что передаю фрески фрагменты в качестве контекста где-то в коде, возможно, это означает, что у каждого из двух фрагментов есть свой собственный кеш ??

@jorgemf - Разве вашему опубликованному коду не нужен соответствующий атрибут transitionName, установленный в макете действия 1? https://developer.android.com/training/material/animations.html

_Начать действие с общим элементом _
...
4 - Назначьте общее имя общим элементам в обоих макетах с помощью атрибута android: transitionName .

Что касается моей проблемы, возможно, мне просто нужно отложить переход. Я посмотрю на это сегодня:
http://www.androiddesignpatterns.com/2015/03/activity-postponed-shared-element-transitions-part3b.html

У меня такая же проблема. Я использую fresco 0.5.3 и SimpleDraweeView, но не загружаю изображение с атрибутом « android: transitionName ». Кто-нибудь знает другое решение, использующее Fresco?

@jorgemf Если вы установите "android-background" в свой Activity1 Layout.xml, он будет работать не идеально, но будет работать.
В своем тесте я установил это: android: background = "@ android: color / transparent "

@LuizGadao Если вы установите фон, вы потеряете все преимущества библиотеки. Я думаю, что это бессмысленно, так как вы хотите, чтобы изображения загружались из Интернета. Не для статических ресурсов в качестве фона.
После тестирования некоторых библиотек у меня все нормально работает. Вообще никаких проблем.

@jorgemf Я с вами согласен. Это всего лишь хитрость для работы.

Есть новости по этому поводу?

@LuizGadao, можете ли вы опубликовать пример XML-

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

Есть новости по этому поводу?

PS:
TranslateDraweeView, предоставляемый @goodev , некорректно работает на некоторых устройствах, таких как XiaoMi2, HuaWei P8. ReenterTransition начинается с неправильной позиции.

Как и сказал boxcounter, Tra slateDraweeView не работает на HTC One M8, ни

Если вы используете ChangeImageTransform Transition, то я думаю, что переход общего элемента не выполняется, потому что ChangeImageTransform анимирует матрицу ImageView, которая, я думаю, не поддерживает DraweeView по умолчанию.

Проблема, с которой я столкнулся, заключается в том, что общий элемент начинается с «fitCenter», тогда как изначально он был «centerCrop».
Проект может воспроизвести проблему
https://github.com/JackFan-Z/ActivitySharedElementTransition.git

Хотя я добавил обходной путь
это не работает в моем другом частном проекте с использованием фрески.
Может ли кто-нибудь узнать, в чем настоящая проблема?

Неправильное начальное состояние перехода
2015-10-01 11 26 34

До перехода
2015-10-01 11 26 50

@ JackFan-Z
Элемент Share при переходе устанавливает окончательный вид на начальные значения и анимирует его до конечных значений.

Обычный ImageView в сочетании с ChangeImageTransform захватывает начальное и конечное значения матрицы изображения, а затем анимирует изменение матрицы изображения.

Однако DraweeView переопределяет определенную функцию, связанную с матрицей изображения, поэтому ChangeImageTransform не окажет никакого влияния на изображение.

Так что в итоге вы получите только ChangeBounds.

В настоящее время я не нашел способа манипулировать матрицей изображений DraweeView. Даже setActualImageMatrix отмечен как устаревший. Предположим, что он не является устаревшим и работает точно так же, как setImageMatrix по умолчанию ImageView по умолчанию. Тем не менее, действительно не очень-то потворствовать анимации его изменения из-за того, что у вас нет никакого способа изменить матрицу после того, как вы установили DraweeViewHierarchy . Таким образом, вам нужно создавать новый DraweeViewHierarchy при каждом вызове onAnimationUpdate .

Я не знаю, почему DraweeView реализован таким образом. И я думаю, что текущее возможное решение - вернуть базовый Bitmap и создать еще один ImageView для выполнения перехода ChangeImageTransform .

@soapsign
Спасибо за ваш комментарий.

На самом деле в моем частном проекте я попытался создать фиктивный ImageView, который принимает то же растровое изображение, что и общий элемент. Проблема все еще существует.
Я не уверен, связана ли проблема, с которой я столкнулся, с фресками.
Но я точно могу воспроизвести ту же проблему с помощью SimpleDraweeView.

ChangeImageTransform использует внутренние размеры для определения матрицы преобразования. Наша реализация DraweeView использует DraweeHierarchy , внутренние размеры которого равны -1 для width и height . Это связано с тем, что Drawee уже применяет правильное масштабирование типа масштабирования, и, следовательно, в представлении нет необходимости делать это. Кроме того, ImageView может применять только один тип масштабирования, тогда как иерархия с возможностью рисования может использовать отдельные типы масштабирования для каждой ветви изображения (заполнитель, изображение сбоя, фактическое изображение и т. Д.). Возврат в представление фактических внутренних размеров просто увеличивает риск появления ошибок определения размера.
Если вы хотите, чтобы переход работал, вы должны использовать ChangeBounds .

Как насчет добавления новой опции, например « fresco: ImageMatrixSrc = actual »?

@boxcounter На данный момент мы думаем, что то, что у нас есть, в порядке. Но вы можете создать пулреквест для своего предложения :)

@massimocarli ChangeBounds работает хорошо, только если общее изображение имеет одинаковый размер для обоих действий / представлений. Но когда изображение следует изменить размер во время перехода, оно обрезается и выглядит плохо.
Что вы предлагаете сделать таким образом? ChangeImageTransform решает эту проблему, но в DraweeView это не работает.

То же самое...

@massimocarli ChangeBounds недостаточно хорош.

Это то, чего я пытаюсь достичь (это использует ImageView): https://gfycat.com/HideousEarlyAndalusianhorse

Вот как это выглядит при использовании SimpleDraweeView: https://gfycat.com/PracticalCorruptGrouper
Обратите внимание на то, как исходное изображение неправильно изменяет размер позади анимированного изображения.

Вот как это выглядит с просто ChangeBounds в качестве перехода: https://gfycat.com/SorrowfulExemplaryAntlion

Привет, ребята, у меня такая же проблема. ChangeBounds не работает плавно. Если есть обходной путь или исправление, сообщите нам. Общий переход элементов - одна из лучших вещей, которые представил материальный дизайн, а фреска - одна из лучших библиотек, которые я использовал до сих пор. Пожалуйста, позвольте разработчикам использовать оба без проблем.

Кто-нибудь смог найти обходной путь, поскольку Fresco этого не исправляет?

Вот обходной путь, который я использую, и он отлично работает:
https://github.com/bumptech/glide

Привет всем,

Самого метода ChangeBounds недостаточно, и я удивлен ответом Facebook о том, что текущее состояние переходов общих элементов в порядке.

Наконец-то я нашел достаточно простое решение, которое, кажется, работает для меня на примере проекта.
Поскольку переход ChangeBounds не обновляет сам макет через onMeasure (), а через onSizeChanged (), который в настоящее время не переопределяется никаким видом чертежа, масштаб вытягиваемого объекта никогда не обновляется во время перехода.

Вот наш CustomDraweeView, который обновляет TopLevelDrawable во время перехода:

public class CustomDraweeView extends SimpleDraweeView {

    public CustomDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
        super(context, hierarchy);
    }

    public CustomDraweeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    <strong i="10">@Override</strong>
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Drawable drawable = getTopLevelDrawable();
        if (drawable != null) {
            drawable.setBounds(0, 0, w, h);
        }
    }
}

Вот xml набора переходов, который вам нужно будет надуть:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:duration="<strong i="14">@android</strong>:integer/config_mediumAnimTime"
    android:transitionOrdering="together"
    tools:targetApi="LOLLIPOP" >
    <changeBounds
        android:interpolator="<strong i="15">@android</strong>:interpolator/accelerate_decelerate"/>
    <changeTransform
        android:interpolator="<strong i="16">@android</strong>:interpolator/accelerate_decelerate"/>
</transitionSet>

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

@massimocarli @tyronen
Может ли кто-нибудь в Facebook дать некоторое представление о том, почему DraweeView в настоящее время не отменяет этот метод, и о возможных проблемах, которые могут возникнуть с этой модификацией? Если ничего не найдено, я с радостью создам для этого запрос на перенос.

Всем привет! В новом выпуске Fresco 0.10 с настраиваемым ScaleType преобразование между разными ScaleType является тривиальным. Вот моя реализация
https://gist.github.com/burzumrus/a589aa7e36ca003ddaf2334218c50ad0

Использование простое

TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeBounds());
transitionSet.addTransition(new DraweeTransform(ScalingUtils.ScaleType.CENTER_CROP, ScalingUtils.ScaleType.FIT_CENTER));
getWindow().setSharedElementEnterTransition(transitionSet);

@burzumrus , это потрясающе! Спасибо за его реализацию. Это именно то, что я имел в виду с InterpolatingScaleType . Подумайте о том, чтобы сделать пул-реквест для Fresco, если это еще не сделано.

@plamenko Я использую фреску 0.12 и

getWindow().setSharedElementEnterTransition(DraweeTransition.createTransitionSet(
                    ScalingUtils.ScaleType.CENTER_CROP, ScalingUtils.ScaleType.CENTER_CROP));
getWindow().setSharedElementEnterTransition(DraweeTransition.createTransitionSet(
                    ScalingUtils.ScaleType.CENTER_CROP, ScalingUtils.ScaleType.CENTER_CROP));

Анимация работает отлично. Но при возвращении к первому действию изображение исчезает.

Кто-нибудь пробовал это с анимацией от фрагмента к фрагменту? Потому что это не работает на v0.12.
Изменить : возможно ли, что RecyclerView вызывает проблемы?
Изменить 2 : Похоже, проблема в том, что ChangeBounds сам использует только координаты X и Y _window_, если для репартинга установлено значение true. Установка его с помощью ChangeBounds setReparenting(true) устарела, и вместо этого рекомендуется ChangeTransform . Таким образом, для RecyclerView также требуется transitionSet.addTransition(new ChangeTransform()); . (Анимация возврата все еще кажется плохой, но, по крайней мере, анимация входа в порядке ( за исключением того, что тип шкалы не влияет на изменение startValues.view на endValues.view в createAnimator(...) решает эту проблему) с это.)

@Gericop и @ ladia12 0.12 хорошо работают в моем проекте в анимации от фрагмента к фрагменту.
Я использую его также в RecyclerView.
Дело в том, что вы можете использовать только транзакцию «заменить» фрагмент. Вы не можете использовать транзакцию «добавить».
Если это может вам помочь, вот пример (без фрески) перехода от фрагмента к фрагменту, который помог мне начать что-то, что сработало (вы можете загрузить код проекта на github)
http://www.androidauthority.com/using-shared-element-transitions-activities-fragments-631996/

@sperochon Я использую replace, и он находится в RecyclerView, но он не работает (и, честно говоря, удивительно, что он работает для вас, может быть, вы используете другую версию RecyclerView? Я использую v24.1.1). Мне пришлось внести несколько изменений, чтобы анимация заработала:

  • добавил ChangeTransform к переходу, установленному через transitionSet.addTransition(new ChangeTransform());

    • это связано с тем, что ChangeBounds сообщает о неправильной позиции начального представления в RecyclerView (всегда возвращает координаты X, Y первого элемента)

  • в createAnimator(...) заменить if (mFromScale == mToScale) на if(mFromScale == mToScale && startBounds.equals(endBounds))

    • преобразование не произойдет в противном случае, если два чертога имеют один и тот же тип шкалы, даже если их размеры не совпадают.

  • в createAnimator(...) замените final GenericDraweeView draweeView = (GenericDraweeView) startValues.view; на final GenericDraweeView draweeView = (GenericDraweeView) endValues.view; (обратите внимание на изменение startValues -> endValues )

    • используйте конечный платёж вместо начального

  • в AnimatorUpdateListener после вызова scaleType.setValue(fraction) вставьте следующие строки:
Drawable drawable = draweeView.getTopLevelDrawable();

if (drawable != null) {
    drawable.setBounds(0, 0, draweeView.getWidth(), draweeView.getHeight());
}

Этот последний фрагмент кода основан на решении @Aohayou (потому что я не мог заставить CustomDraweeView работать).
Проверено на Android 5.0.2 с поддержкой версии v24.1.1 библиотеки.

ОБРАТИТЕ ВНИМАНИЕ, что это решение не будет работать, если вы будете анимировать изображения с одинаковыми размерами.

@Gericop Вот демонстрация, которая отлично работает. Я только что зафиксировал это на github. Я старался по максимуму почистить код. Будьте осторожны: я использовал только одно изображение в моем представлении ресайклера, потому что имя перехода должно отличаться для каждого элемента в представлении ресайклера, чтобы Fresco работала. Итак, для упрощения я использовал только 1 изображение с 1 названием перехода.
https://github.com/sperochon/DemoFrescoFragment2Fragment

Надеюсь на эту помощь!

@sperochon Попробуйте использовать несколько изображений.
Кстати, я тестировал вашу демонстрацию с неизмененным исходным кодом. Вот результат:

device-2016-08-14-220810_1

Это совершенно неверно. Конечный вид начинается с другой позиции, и тип шкалы не имеет никакого значения. Я не знаю, как вы можете сказать по этому поводу, что «это прекрасно работает», потому что это явно не так.

@Gericop Я только что обновил код. Я забыл указать другую раскладку для конечного фрагмента. Попробуй еще раз, пожалуйста.

@sperochon В эмуляторе API 23 работает нормально. На моем устройстве (API 21) этого не происходит. Также тестировал в эмуляторе API 21, там тоже не работает.
Итак, суть в следующем: текущая реализация не работает с API 21 (не тестировала ее на API 22), но работает с API 23.

Изменить : ваша демонстрация проверяет только переходы по умолчанию ChangeBounds и ChangeTransform , а не реализацию DraweeTransition предоставленную Facebook.

К сожалению, вы правы ... Проверял на своих устройствах:
Android 5.0 + Fresco v0.11 / v0.12 -> KO
Android 6.0 + Fresco v0.11 / v0.12 -> ОК
Раньше не замечал ...

@Gericop @sperochon Я написал об этом сообщение в

@ ladia12 Этот пост не имеет ничего общего с проблемой, с которой я столкнулся (мы) ... Ваша запись в блоге посвящена переходу _inter- Activity _, а моя проблема связана с _inter- Fragment _. Более того, настоящая ошибка заключается в том, как API 21 обрабатывает переходы ChangeBounds и / или ChangeTransform где Facebook предоставил DraweeTransition тоже не помогает. Мое решение, с другой стороны, преодолевает это, если исходное и целевое изображения имеют разные размеры (ширину и / или высоту).

Только для информации:
Android 5.0 + Fresco v0.11 / v0.12 / 0.13 -> KO
Android> = 5.1 + Fresco v0.11 / 0.12 / 0.13 -> ОК

@ ladia12 Как вы решили проблему исчезновения исходного изображения при возврате к первому действию?

@dbrant У меня такая же проблема. Вы нашли способ ее решить?

См. №1446

@ ladia12 Как вы решили проблему исчезновения исходного изображения при возврате к первому действию?

@ ladia12 Как вы решили проблему исчезновения исходного изображения при возврате к первому действию? Мое исходное изображение находится в держателе просмотра recyclerview

В итоге я использовал Пикассо для перехода к общим элементам. Это не было исправлено
во фреске. Так что Picasso легкий, и нет никаких проблем с его использованием.
вместе с Фреско.

В среду, 19 июня 2019 г., в 17:11 bembem1011 [email protected] написал:

@ ladia12 https://github.com/ladia12 Как вы решили проблему
исходное изображение исчезает при возврате к первому действию? Мой
исходное изображение находится в держателе просмотра recyclerview

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/facebook/fresco/issues/22?email_source=notifications&email_token=AAXQ5WYUP5KBJYNBOZX7CCDP3ILM5A5CNFSM4A6ZMH32YY3PNVWWWK3TUL52HS4DFVREXueG43V2HS4DFVREXG63V2HS4DFVREXG43V2HS4DFVREXG43VB
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAXQ5W5EXO5SV4R2PXVTG7LP3ILM5ANCNFSM4A6ZMH3Q
.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги