Fresco: Поделиться Element Gone после SharedElementReturnTransition в Android N

Созданный на 31 авг. 2016  ·  70Комментарии  ·  Источник: facebook/fresco

Я использую новейший код фрески для выполнения работы SharedElement Transition , он хорошо работает в Android L 、 M , Но на Android N все идет не так

до перехода
screenshot0

после перехода
screenshot0

bug help wanted

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

Просто добавьте этот код в действие вызова , + 1, если это может вам помочь !!! @oprisnik


setExitSharedElementCallback(new SharedElementCallback() {

            <strong i="6">@Override</strong>
            public void onSharedElementEnd(List<String> sharedElementNames,
                                           List<View> sharedElements,
                                           List<View> sharedElementSnapshots) {

                super.onSharedElementEnd(sharedElementNames, sharedElements,
                        sharedElementSnapshots);

                for (View view : sharedElements) {
                    if (view instanceof SimpleDraweeView) {
                        view.setVisibility(View.VISIBLE);
                    }
                }
            }
        });

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

Не могли бы вы показать, как вы выполняете переходную часть с помощью демонстрационного приложения Fresco?

activity_main.xml и activity_detail имеют один и тот же SimpleDraweeView с одинаковым именем перехода
и в методе onCreate DetailActivity, как показано ниже:

protected void onCreate (Bundle savedInstanceState) {
getWindow (). requestFeature (Window.FEATURE_CONTENT_TRANSITIONS);
getWindow (). setSharedElementEnterTransition (DraweeTransition.createTransitionSet (ScalingUtils.ScaleType.CENTER_CROP, ScalingUtils.ScaleType.FIT_CENTER));
getWindow (). setSharedElementReturnTransition (DraweeTransition.createTransitionSet (ScalingUtils.ScaleType.FIT_CENTER, ScalingUtils.ScaleType.CENTER_CROP));
addTransitionListener ();
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_detail);
mBaselineJpegView = (SimpleDraweeView) findViewById (R.id.baseline_jpeg);
mBaselineJpegView.setImageURI (Uri.parse ("https://www.gstatic.com/webp/gallery/1.sm.jpg"));
mBaselineJpegView.setOnClickListener (новый View.OnClickListener () {
@Override
public void onClick (View v) {
Toast.makeText (DetailActivity.this, «dsasa», Toast.LENGTH_LONG) .show ();
}
});
}

addTransitionListener () ничего не делает, просто печатает журнал

так что я использую неправильный способ перехода?

Это тоже происходит со мной.

У меня есть следующий метод onCreate () до super.onCreate ()

supportRequestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
Transition fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);
Window window = getWindow();
window.setEnterTransition(fade);
window.setReturnTransition(fade);
window.setExitTransition(fade);
TransitionSet transitionSet = DraweeTransition
                    .createTransitionSet(ScalingUtils.ScaleType.CENTER_CROP,
ScalingUtils.ScaleType.CENTER_CROP);
window.setSharedElementEnterTransition(transitionSet);
window.setSharedElementExitTransition(transitionSet);

У меня такая же проблема. SetSharedElementReturnTransition не работает на Android N. Я добавил журналы для прослушивателей переходов, и onTransitionStart и onTransitionEnd не запускаются на Android N, но на Android M & L он работает нормально.
Я использую последнюю версию библиотеки Fresco com.facebook. фреска: фреска : 0.14.1 с com.facebook. фреска: imagepipeline-okhttp3 : 0.14.1
У меня нет этой проблемы, если я использую библиотеку Picasso для загрузки изображения.
Сценарий аналогичен: gridView, gridItem переходит к другому Activity (с этой частью все в порядке), но когда я возвращаюсь, повторного входа нет, изображение мигает и перезагружается (изображение-заполнитель не отображается, ни изображение, которое было уже загружен). Это происходит только на Android N (7.0).

Есть новости по этой проблеме?

Переключился с Fresco на Picasso, и проблема решена. Жаль, что эта библиотека не поддерживается так часто, как того требуют новые версии ОС Android.

Кажется, что эта проблема неправильно помечена как «требуется-детали». Эта проблема также существует на Android 7.1.1 (уровень API 25).

Спасибо мы посмотрим

У меня такая же проблема, поэтому +1 от меня за ее исправление.

то же самое

Сделай это. Сделай это. ;-)

Да, пожалуйста.

Пожалуйста...

+1

Интересно, почему это не так важно?

+1

Когда я прокручиваю до позиции общего элемента в onActivityReenter исчезнувший элемент возвращается, хотя и с небольшим мерцанием белого цвета:

    <strong i="7">@Override</strong>
    public void onActivityReenter(int resultCode, Intent data) {
        super.onActivityReenter(resultCode, data);

        final int position = data.getIntExtra(EXTRA_GIF_POSITION, -1);
        if (resultCode == RESULT_OK && position != -1) {
            gifRecyclerView.getLayoutManager().scrollToPosition(position);
        }
    }

Если кто-то знает лучшее исправление, я был бы признателен, если бы вы могли поделиться им.

Здравствуйте, у меня такая же проблема, но только на Android 7.1.1 API 25

Если есть какие-либо обновления по этой проблеме, я был бы очень признателен.

То же самое здесь на emu с 7.x, но я использую onWindowFocusChanged для иммерсивного эффекта, когда закончится, изображение исчезнет, ​​но отобразится мгновенно.

То же самое. Вызов requestLayout в представлении, содержащем SimpleDraweeView, похоже, исправляет его с некоторым мерцанием. пожалуйста, порекомендуйте

Просто добавьте этот код в действие вызова , + 1, если это может вам помочь !!! @oprisnik


setExitSharedElementCallback(new SharedElementCallback() {

            <strong i="6">@Override</strong>
            public void onSharedElementEnd(List<String> sharedElementNames,
                                           List<View> sharedElements,
                                           List<View> sharedElementSnapshots) {

                super.onSharedElementEnd(sharedElementNames, sharedElements,
                        sharedElementSnapshots);

                for (View view : sharedElements) {
                    if (view instanceof SimpleDraweeView) {
                        view.setVisibility(View.VISIBLE);
                    }
                }
            }
        });

такая же проблема здесь ...

Я не знаю, поможет ли это найти решение, но я заметил, что при открытии программной клавиатуры SimpleDraweeView становится видимым.

У меня была такая же проблема, и она была исправлена ​​после этих двух вызовов:

  1. Непосредственно перед startActivity(... :
    setExitSharedElementCallback(new SharedElementCallback() {
                <strong i="9">@Override</strong>
                public void onSharedElementEnd(List<String> names,
                                               List<View> elements,
                                               List<View> snapshots) {
                    super.onSharedElementEnd(names, elements, snapshots);
                    for (final View view : elements) {
                        if (view instanceof SimpleDraweeView) {
                            view.post(() -> view.setVisibility(View.VISIBLE));
                        }
                    }
                }
            });
  1. Внутри onCreate нового действия:
setEnterSharedElementCallback(new SharedElementCallback() {
                <strong i="15">@Override</strong>
                public void onSharedElementEnd(List<String> names,
                                               List<View> elements,
                                               List<View> snapshots) {
                    super.onSharedElementEnd(names, elements, snapshots);
                    for (final View view : elements) {
                        if (view instanceof SimpleDraweeView) {
                            view.post(() -> view.setVisibility(View.VISIBLE));
                        }
                    }
                }
            });

@oprisnik есть обновления по этому
Я все еще испытываю это с API 24+, когда общий элемент является элементом внутри RecyclerView .
Ни один из обходных путей, перечисленных в этой заявке, у меня не сработал (представление никогда не устанавливается на невидимое / исчезнувшее).
Я использую DraweeTransition.createTransitionSet() как для входа, так и для возврата.
Иногда изображение исчезает до тех пор, пока не будет прокручено recyclerview, иногда оно возвращается с мерцанием через некоторое время (может быть вызвано вызовом notifyDataSetChanged ()).

Не уверен, что это поможет, но это то, что происходит во Fresco согласно журналам, когда второе действие закрывается и общий элемент возвращается на свою позицию:

V/unknown:AbstractDraweeController: controller c6a03e3 9: onDetach
V/unknown:AbstractDraweeController: controller c6a03e3 9: release: image: CloseableReferenceWithFinalizer f25d513
V/unknown:AbstractDraweeController: controller f84c24e 4: onAttach: request needs submit
V/unknown:AbstractDraweeController: controller f84c24e 4: set_final_result @ onNewResult: image: CloseableReferenceWithFinalizer f25d513

Это происходит, когда растровое изображение отображается снова.
Когда растровое изображение не отображается, два последних события не происходят:

V/unknown:AbstractDraweeController: controller f84c24e 4: onAttach: request needs submit
V/unknown:AbstractDraweeController: controller f84c24e 4: set_final_result @ onNewResult: image: CloseableReferenceWithFinalizer f25d513

@marcosalis При возврате к первому действию (с recyclerView). Всегда ли это вызывает notifyDataSetChanged ()?

@erikandre спасибо за ответ;)
После некоторых тестов я могу подтвердить, что notifyDataSetChanged () не вызывается, даже когда растровое изображение отображается само по себе.

Это состояние SimpleDraweeView если я помещаю точку останова в SharedElementCallback.onSharedElementEnd() в вызывающем действии.

 DraweeHolder{controllerAttached=false, holderAttached=true, drawableVisible=false}

PipelineDraweeController{super=PipelineDraweeController{isAttached=false, isRequestSubmitted=false, hasFetchFailed=false, fetchedImage=0, events=[...]}, dataSourceSupplier={request=ImageRequest{uri=https://OMITTED, cacheChoice=DEFAULT, decodeOptions=100-false-false-false-false-ARGB_8888-null, postprocessor=null, priority=HIGH, resizeOptions=null, rotationOptions=-1 defer:true, mediaVariations=null}}}

Я думаю, это может иметь какое-то отношение к методам doDetach() и doAttach() в SimpleDraweeView , когда само представление находится в RecyclerView .
Наконец, это сработало для меня (добавлено в Activity, из которого создается переход), хотя это не очень чисто:

        setExitSharedElementCallback(new SharedElementCallback() {
            <strong i="11">@Override</strong>
            public void onSharedElementEnd(List<String> names, List<View> elements, List<View> snapshots) {
                for (View view : elements) {
                    if (view instanceof SimpleDraweeView) {
                        view.post(() -> {
                                myAdapter.notifyDataSetChanged();
                        });
                    }
                }
            }
        });

@marcosalis Замечательно, что вы нашли обходной путь! Я попытался воспроизвести эту конкретную проблему в приложении Showcase, работающем на Genymotion с Android 7, но безуспешно.

Как выглядят просмотры элементов для recyclerview? В моем случае это был просто FrameLayout, оборачивающий SimpleDraweeView.

@marcosalis ваше решение сработало для меня с небольшим изменением, удалив цикл for:

setExitSharedElementCallback(
                    new SharedElementCallback() {
                        <strong i="7">@Override</strong>
                        public void onSharedElementEnd(List<String> names, List<View> elements, List<View> snapshots) {
                            super.onSharedElementEnd(names, elements, snapshots);
                            notifyDataSetChanged();
                        }
                    }
            );

Я только что наткнулся на ту же проблему, играя с переходами между действиями. Похоже, что ни один из предложенных выше обходных путей не помог. (API 25) Вот как это выглядит: https://vimeo.com/225497240

Я думаю, что мы нашли обходной путь, и надеюсь, что исправление будет доступно в ближайшее время.

Обходной путь можно найти в dc7ec2436fc9b639fe1a39398712c360b16da468.

На данный момент вам нужно настроить первый DraweeView которого начинается переход, чтобы использовать устаревшую обработку видимости, вызвав simpleDraweeView.setLegacyVisibilityHandlingEnabled(true); (как вы можете видеть в примере перехода в нашем примере приложения Showcase) .

Не могли бы вы проверить, решает ли это проблему для вас? Мы собираемся выпустить новую версию Fresco, которая содержит это исправление очень скоро.

Ага, спасибо! Подтверждено, что это решает проблему. С нетерпением жду обновленной версии.

Мы выпустили Fresco v1.4.0 , которая включает исправление, упомянутое выше. Просто позвоните simpleDraweeView.setLegacyVisibilityHandlingEnabled(true); и теперь он должен работать.

Мы также обновили образец перехода «Витрина», чтобы отразить эти изменения.

Спасибо за это исправление, в моем случае это сработало идеально. Один вопрос, почему бы не поставить setGlobalLegacyVisibilityHandlingEnabled на true по умолчанию? Есть проблемы с производительностью?

Обработка видимости изменилась с Android N, и мое изменение (отчасти) возвращает поведение к предыдущему состоянию. Изменение этого поведения для всех изображений может привести к другим неожиданным проблемам, поэтому мы решили пока не включать его по умолчанию. Убедившись в отсутствии побочных эффектов, мы рассмотрим возможность включения его по умолчанию.
Не стесняйтесь установить его на true и сообщать о любых проблемах, с которыми вы сталкиваетесь.

ezgif com-resize

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

Фреска 1.5.0, Орео

Изменить: проработав еще пару дней и переместив некоторые виды, я обнаружил, что проблема больше не возникает на моем пиксельном устройстве Oreo. На моем эмулированном Nexus 5x API 24 изображение всегда остается пустым после анимации выхода.

У меня такая же проблема с setLegacyVisibilityHandlingEnabled . Установка его на true работает в большинстве случаев, но иногда, случайно, изображение исчезает после обратного перехода.

@marcosalis это происходит только на Oreo или также на Nougat?

Привет, @oprisnik, мне удалось воспроизвести его случайным образом на Samsung S7 (Nougat) и на эмуляторе на API 26. Сообщите мне, могу ли я помочь в его отладке.

Спасибо, попробую перепроверить, когда у меня будет еще немного времени

@oprisnik
Могу подтвердить, что большую часть времени кажется, что он не выполняет свою работу (API24 + API25)

Однако мне удалось заставить его немного поработать, используя следующий прием:

        setExitSharedElementCallback(new SharedElementCallback() {
            <strong i="8">@Override</strong>
            public void onSharedElementEnd(List<String> names,
                                           List<View> elements,
                                           List<View> snapshots) {
                super.onSharedElementEnd(names, elements, snapshots);
                for (final View view : elements) {
                    if (view instanceof SimpleDraweeView) {
                        view.post(() -> {
                            view.setVisibility(View.VISIBLE);
                            view.requestLayout();
                        });
                    }
                }
            }
        });

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

Привет @oprisnik ,
Вы нашли другое решение?

Пока нет, это сложно исправить, поскольку Google изменил поведение видимости View, что нарушает обработку видимости Fresco (которая нам нужна для управления памятью), и у меня также не будет много времени, чтобы изучить это в ближайшем будущем. . Однако в этом потоке упоминается несколько альтернатив, которые решают проблему (например, обходной путь от

Если кто-то захочет разобраться в этом, всегда приветствуются запросы на вытягивание! :)

@oprisnik , эта проблема также затронула модуль react-native-maps .
Я пометил эти строки как комментарии в файле RootDrawable.java в качестве временного решения.
Вы помните / знаете какую-либо серьезную проблему, связанную с пометкой этих строк как строк комментариев?

Возникла та же проблема, что и у поздних версий ).

Их решение устранило все мои проблемы.

@efkan Точно не знаю. Я помню, что я тоже изучал это, когда искал альтернативные исправления, но отклонил это. Я думаю, что одна проблема с удалением этих проверок заключается в том, что базовое растровое изображение было выпущено (поскольку представление больше не отображается), и попытка его нарисовать вызовет java.lang.RuntimeException: Canvas: trying to use a recycled bitmap ... поскольку BitmapDrawable не выполнять любые проверки на вменяемость.

Сам ImageView имеет ту же ошибку, когда он не восстанавливает должным образом видимость Drawable для любого рисованного объекта, но он все еще работает, поскольку большинство Drawables не выполняют проверку видимости и нет ручного управления памятью - и базового Bitmap все равно будет в силе.

@oprisnik спасибо за все эти объяснения.

Чтобы проверить, работает ли это, довольно легко добавить это как параметр в GenericDraweeHierarchyBuilder и, в зависимости от этого, игнорировать проверку видимости в RootDrawable (который создается в GenericDraweeHierarchy см. https://github.com/facebook/fresco/blob/master/drawee/src/main/java/com/facebook/drawee/generic/GenericDraweeHierarchy.java#L155).

Не стесняйтесь отправлять PR, который добавляет этот параметр, чтобы вы могли включить его для своих приложений и посмотреть, есть ли побочные эффекты.

Такая же проблема появляется только на устройствах с Android 7.1 (или выше).
Ни одно из вышеперечисленных решений не работает.
Проблема всегда возникает, когда скорость сети ограничена 10 кбит / с.

@ babyblue1314 - Упомянутое выше изменение RootDrawable тоже вас не исправит?

@oprisnik Спасибо за быстрый ответ!
Эм ... Я полагаю, что упомянутое выше изменение RootDrawable также не исправляет это для меня.
Не знаю, использовал ли я это неправильно. Вот как это выглядит:

Перед использованием изменения RootDrawable:

После использования изменения RootDrawable:

_ Я должен упомянуть, что скорость сети ограничена 10 кбит / с. _
Более того, это отображается не только в ListView, но также в RecyclerView и GridView, как показано ниже:

Мой код:

  1. ListViewAdapter (или RecyclerViewAdapter или GridViewAdapter):
SimpleDraweeView thumbnail = cholder.getView(R.id.thumbnail);

GenericDraweeHierarchyBuilder hierarchyBuilder = new GenericDraweeHierarchyBuilder(thumbnail.getContext().getResources());
GenericDraweeHierarchy hierarchy = hierarchyBuilder.build();
hierarchy.getTopLevelDrawable().setVisible(true, false);
thumbnail.setHierarchy(hierarchy);

ImageLoaderUtil.loadImage(thumbnail, item.getLogourl(), 696, 288);
  1. ImageLoaderUtil:
Uri uri = Uri.parse(url);
ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(uri);
imageRequestBuilder.setRotationOptions(RotationOptions.autoRotate()); 
imageRequestBuilder.setImageDecodeOptions(new ImageDecodeOptions(ImageDecodeOptions.newBuilder()
.setBitmapConfig(Bitmap.Config.RGB_565)));
imageRequestBuilder.setResizeOptions(new ResizeOptions(reqWidth, reqHeight));
ImageRequest imageRequest = imageRequestBuilder.build();

PipelineDraweeControllerBuilder draweeControllerBuilder = Fresco.newDraweeControllerBuilder();
draweeControllerBuilder.setOldController(simpleDraweeView.getController());
draweeControllerBuilder.setImageRequest(imageRequest);
draweeControllerBuilder.setTapToRetryEnabled(false); 

DraweeController draweeController = draweeControllerBuilder.build();
simpleDraweeView.setController(draweeController);

Фреска 1.5.0

Устройство: Lenovo, android 7.1.1

_Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

@ babyblue1314 Я не вижу переходов в ваших видео или коде, связанном с переходами. Вы уверены, что говорите об одной и той же проблеме?

@oprisnik Извините, я только что понял, что эта проблема перехода отличается от моей проблемы.
Я видел, что явление похоже на мое, так что ……
Стоит ли начинать новый выпуск?

@ babyblue1314 да, пожалуйста, это совершенно не связано.

@oprisnik Я наконец нашел причину своей проблемы.
В случае недопонимания других людей я здесь, чтобы дать некоторые объяснения.
Моя проблема связана с форматом изображения.
Если я использую метод imageRequestBuilder.setProgressiveRenderingEnabled(true) с форматом PNG, мою проблему всегда можно воспроизвести.
Если я изменю метод на imageRequestBuilder.setProgressiveRenderingEnabled(false) с форматом PNG, все будет работать нормально.
@oprisnik Еще раз спасибо за терпение!

Пожалуйста, исправьте эту проблему ...

Fresco 1.9.0 не решает проблему должным образом.
Смесь предложений в этой теме исправляет это в зависимости от устройства:

Поэтому я использую оба обходных пути в своем коде, чтобы быть в безопасности, и, надеюсь, это все покрывает. @oprisnik Я потрачу некоторое время, чтобы попытаться лучше разобраться в проблеме, если найду исправление, я отправлю PR.

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

Тем не менее, эта проблема связана с компонентом react-native-maps. Я полагаю, это параллельная проблема?
Вы хоть представляете, в чем проблема?

Есть ли прогресс в выявлении проблемы? Кажется, мы ничего не слышим с апреля.

У нас все еще не было времени на дальнейшее расследование того, что здесь происходит. Не стесняйтесь изучить проблему и отправить запрос на перенос!

Как упоминалось ранее, основная проблема, по-видимому, связана с ошибкой фреймворка Android, когда ImageView не восстанавливает должным образом видимость базового Drawable при возврате из перехода.

Я отправил отчет об ошибке Android здесь: https://issuetracker.google.com/issues/111293868

Я также создал образец приложения (не Fresco), в котором описывается проблема: https://github.com/oprisnik/VisibilityPlayground

Мы рассмотрим, найдется ли обходной путь для этой проблемы. Однако Fresco требует ручного управления памятью, и мы полагаемся на видимость Drawable для повторного запроса изображения, поэтому я не уверен, есть ли лучшее исправление, чем описанные выше обходные пути.

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

На самом деле недействительный или View.setVisibility не может отображать drawable, вам нужно напрямую вызвать Drawable.setVisible (true, true).
Я добавляю эти коды в A Activity # OnCreate, все работает нормально:

ActivityCompat.setExitSharedElementCallback(this, new SharedElementCallback() {
            <strong i="7">@Override</strong>
            public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
                super.onSharedElementEnd(sharedElementNames, sharedElements, sharedElementSnapshots);
                if (FP.empty(sharedElements)) {
                    return;
                }
                for (View view : sharedElements) {
                    if (view instanceof SimpleDraweeView) {
                        ((SimpleDraweeView) view).getDrawable().setVisible(true, true);
                    }
                }
            }
        });

@oprisnik В вашем примере приложения, не связанного с фресками, вы устанавливаете переход на ChangeBounds . Ошибка возникает, если убрать эту строку? Я предполагаю, что видимость восстанавливается правильно, когда ChangeImageTransform находится в игре. Можно ли заставить фрески работать с ChangeImageTransform ?

@RainFool прав. simpleDraweeView.getVisibility () - это VISIBLE , но simpleDraweeView.getDrawable (). isVisible () - это false .

Да, это ошибка в платформе Android, из-за которой видимость представления (точнее, ImageView) не распространяется на Drawable, поэтому вам нужно вручную обновить видимость. Пометьте отчет об ошибке Android здесь, чтобы он стал более заметным: https://issuetracker.google.com/issues/111293868

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