我使用最新的fresco代码做SharedElement Transition工作,在Android L、M上运行良好,但在Android N上却出错
过渡前
过渡后
你能展示一下你是如何使用 Fresco 的演示应用程序进行过渡部分的吗?
activity_main.xml 和 activity_detail 具有相同的 SimpleDraweeView 和相同的 transitionName
在 DetailActivity 的 onCreate 方法中,如下所示:
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(new View.OnClickListener() {
@覆盖
public void onClick(View v) {
Toast.makeText(DetailActivity.this, "dsasa", Toast.LENGTH_LONG).show();
}
});
}
addTransitionListener() 什么都不做,只是打印日志
那么我是否使用错误的方式进行转换?
这也发生在我身上。
我在 super.onCreate() 之前的 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
如果有关于该问题的任何更新,我将不胜感激。
在 7.x 的 emu 上也是如此,但我使用 onWindowFocusChanged 是身临其境的,当完成时图像会消失但会立即重新显示。
同样在这里。 在包含 SimpleDraweeView 的视图上调用 requestLayout 似乎用一些闪烁修复它。 请指教
只需在调用活动中添加此代码,如果可以帮助您+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);
}
}
}
});
同样的问题在这里... @antxyz我已经将您的代码放在 onCreate 方法的调用和被调用活动中,但没有成功。 返回过渡后共享元素图像仍然不可见。
我不知道它是否有助于找到解决方案,但我注意到打开软键盘时,SimpleDraweeView 变得可见。
我遇到了同样的问题,在这两次调用后它被修复了:
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));
}
}
}
});
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 有任何更新吗? 很遗憾它还没有修复。
当共享元素是RecyclerView
一个项目时,我仍然在使用 API 24+ 时遇到这种情况。
这张票上列出的所有解决方法都不适合我(视图从未设置为不可见/首先消失)。
我正在使用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(),即使位图单独显示也是如此。
如果我在调用活动中的SharedElementCallback.onSharedElementEnd()
中放置断点,这就是SimpleDraweeView
的状态。
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太好了,您找到了解决方法! 我试图在使用 Android 7 的 Genymotion 上运行的 Showcase 应用程序中重现这个特定问题,但没有成功。
recyclerview 的项目视图是什么样的? 就我而言,它只是一个包装 SimpleDraweeView 的 FrameLayout。
@marcosalis您的解决方案对我
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 :
我想我们找到了一个解决方法,希望很快就会有一个修复程序。
解决方法可以在 dc7ec2436fc9b639fe1a39398712c360b16da468 中找到。
现在,您必须通过调用simpleDraweeView.setLegacyVisibilityHandlingEnabled(true);
来设置第一个DraweeView
开始转换的位置,以使用旧版可见性处理(正如您在我们的 Showcase 示例应用程序中的转换示例中所见) .
你能检查一下这是否能解决你的问题吗? 我们将很快发布一个包含此修复程序的新 Fresco 版本。
是的,谢谢! 确认这解决了问题。 期待更新的版本。
我们已发布Fresco v1.4.0 ,其中包含上述修复程序。 只需调用simpleDraweeView.setLegacyVisibilityHandlingEnabled(true);
就可以了。
我们还更新了Showcase 转换示例以反映这些更改。
感谢您的修复,在我的情况下它工作得很好。 一个问题,为什么不把setGlobalLegacyVisibilityHandlingEnabled
默认放到true
? 有什么性能问题吗?
可见性处理随着 Android N 发生了变化,我的变化是(有点)将行为恢复到 N 之前。 更改所有图像的此行为可能会导致其他意外问题,这就是我们决定默认情况下不启用它的原因。 一旦我们确认没有副作用,我们就会考虑默认开启它。
随意将其设置为true
并报告您遇到的任何问题。
此修复程序似乎无法随机工作。 我将 setGlobalLegacyVisibilityHandlingEnabled 设置为 true,但单击几下后,返回的图像为空白。
壁画 1.5.0,奥利奥
编辑:在开发了几天并移动了一些视图之后,我发现这个问题在我的奥利奥像素设备上不再发生了。 在我模拟的 Nexus 5x API 24 上,退出动画后图像始终为空白。
我对setLegacyVisibilityHandlingEnabled
有同样的问题。 将其设置为true
大部分时间都有效,但有时,只是随机地,图像在返回转换后消失。
@marcosalis只发生在奥利奥或牛轧糖上吗?
嗨@oprisnik我已经设法在三星 S7 (Nougat) 和 API 26 的模拟器上随机重现它。让我知道我是否可以帮助调试它。
谢谢,等我有时间再试试
@oprisnik
可以确认它似乎在大多数时候都没有完成它的工作(API24 + API25)
但是,我设法使用以下 hack 让它有些工作:
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 ,
您找到不同的解决方法了吗?
还没有,这很难解决,因为谷歌改变了视图可见性行为,这破坏了 Fresco 的可见性处理(我们需要用于内存管理)而且我也不会在不久的将来有很多时间来研究这个. 但是,此线程中提到了几个解决此问题的替代方法(例如来自@MartB 的手动设置可见性的解决方法)。
如果有人想研究这个,总是欢迎拉请求! :)
@oprisnik , react-native-maps
模块也受到此问题的影响。
我已将这些行标记为 RootDrawable.java 文件中的注释作为解决方法。
您还记得/知道与将这些行标记为注释行相关的任何大问题吗?
遇到与@efkan相同的问题,
他们的解决方案解决了我遇到的所有问题。
@efkan我不完全清楚。 我记得我在寻找替代修复程序时也研究过这个问题,但没有考虑。 我认为删除这些检查的一个问题是底层位图已被释放(因为视图不再可见)并且尝试绘制它会抛出java.lang.RuntimeException: Canvas: trying to use a recycled bitmap ...
因为BitmapDrawable
没有执行任何健全性检查。
ImageView
本身也有同样的错误,它不能正确恢复任何可绘制对象的可绘制可见性,但它仍然有效,因为大多数可绘制对象不进行可见性检查并且没有手动内存管理 - 以及底层位图仍然有效。
@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(或更高版本)的设备上。
以上解决方案均无效。
当网络限制为 10kb/s 时,问题总是出现。
@babyblue1314 - 上面提到的RootDrawable
更改也不能为您解决问题?
@oprisnik感谢您的快速回复!
Em...我想是的,上面提到的 RootDrawable 更改也没有为我修复它。
不知道是不是我用错了。 这是它的样子:
_我应该提到网络限制为 10kb/s。 _
更重要的是,这不仅会出现在 ListView 中,还会出现在 RecyclerView 和 GridView 中,如下所示:
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);
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);
_如果您需要更多信息,请告诉我。
@babyblue1314我在您的视频或与过渡相关的代码中没有看到任何过渡。 你确定你在谈论同样的问题吗?
@oprisnik抱歉,我刚刚意识到这个过渡问题与我的问题不同。
我看到这个现象和我的很相似,所以……
我应该开始一个新的问题吗?
@babyblue1314是的,拜托,这似乎无关紧要。
@oprisnik我终于找到了问题的原因。
万一误会了别人,我在这里做一些解释。
我的问题与图片格式有关。
如果我使用带有 PNG 格式的imageRequestBuilder.setProgressiveRenderingEnabled(true)
方法,我的问题总是可以重现。
如果我使用 PNG 格式将方法更改为imageRequestBuilder.setProgressiveRenderingEnabled(false)
,则一切正常。
@oprisnik再次感谢您的耐心等待!
请修复这个问题...
Fresco 1.9.0 没有正确解决这个问题。
该线程中的命题混合修复它取决于设备:
setLegacyVisibilityHandlingEnabled
和单独的onSharedElementEnd
解决方法都有效。onSharedElementEnd
解决方法之外什么都不做。所以我在我的代码中使用了这两种解决方法,以确保我的代码安全,并希望涵盖所有内容。 @oprisnik我会花一些时间来尝试更好地理解问题,如果我找到解决方法,我会提交 PR。
是的,不幸的是,我们仍然没有很好地解决此问题,因为此线程中提到的所有解决方案都以一种或另一种方式失败。 如果有人对如何正确解决此问题有想法,请告诉我们,或者更好的是,提交 PR :)
尽管如此,关于 react-native-maps 组件的这个问题。 我想这是一个并发问题?
你知道问题出在哪里吗?
在查明问题方面有任何进展吗? 自四月以来,我们似乎没有听到任何消息。
我们仍然没有时间进一步调查这里发生的事情。 随时查看问题并提交拉取请求!
我切换到壁画没有意识到这个问题。 我渲染了大量的 gif,效果很好,但我也依赖这些动画进行导航。 我已经能够使用上面提到的技巧,但是在返回动画时,图像会消失。
实际失效或者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在您的非壁画示例应用程序中,您将转换设置ChangeImageTransform
起作用时,能见度会正确恢复。 是否可以让壁画图像与ChangeImageTransform
?
@RainFool是对的。 simpleDraweeView.getVisibility() 是VISIBLE
,但 simpleDraweeView.getDrawable().isVisible() 是false
。
是的,这是 Android 框架中的一个错误,其中 View 可见性(准确地说是 ImageView)没有传播到 Drawable,因此您必须手动更新可见性。 请在此处为 Android 错误报告加注星标,以便获得更多可见性: https :
最有用的评论
只需在调用活动中添加此代码,如果可以帮助您+1 ! @oprisnik