Fresco: 共享元素过渡

创建于 2015-03-28  ·  57评论  ·  资料来源: facebook/fresco

共享元素转换似乎不起作用。

在带有 android 5.0 的摩托罗拉设备中测试

最有用的评论

这是我使用的工作正常的解决方法:
https://github.com/bumptech/glide

所有57条评论

你能给我们更多的细节吗? 你到底想做什么,结果发生了什么?

在新的 android 版本棒棒糖中,我们可以使用 ImageView 作为 Activity 之间的共享元素过渡。 在这种情况下,图像会从一个活动平滑过渡到下一个活动。 使用 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 的右下角移动和调整大小的活动之间进行转换。我测试了类似的代码从网络加载图像,但它不显示动画。

我怀疑这与视图在转换时获得的附加/分离事件有关。 我们必须对此进行调查。

这也是我可以确认的。 共享元素转换似乎在 Fresco 上被破坏了。 如果我们能解决这个问题就太好了,因为这是一个非常重要的功能。

也发生在我身上。 将 transtitionName xml attr 设置为 SimpleDraweeView 时,setImageUri() 方法停止工作

有任何更新吗?

FadeDrawable完成动画实景后,有一个日志:
com.facebook.samples.comparison D/ViewRootImpl﹕changeCanvasOpacity: opaque=false

也许 changeCanvasOpacity 导致图像无法绘制。

错误修复了吗? 这对我的项目也非常重要。 :)

包 org.goodev.droidddle.drawee;

导入 com.facebook.drawee.generic.GenericDraweeHierarchy;
导入 com.facebook.drawee.view.SimpleDraweeView;

导入 android.content.Context;
导入 android.graphics.Matrix;
导入 android.util.AttributeSet;

公共类 TranslateDraweeView 扩展 SimpleDraweeView {
公共 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 的标准设置:

  • 带有 GridLayoutManager 的片段中的 RecyclerView 将大量图像显示为 SimpleDraweeViews,在 viewholder 绑定方法中动态设置它们的 transitionName(我也在其中设置 uri)
  • OnClick 使用单个 SimpleDrawee 视图触发到不同片段的转换,并且相同的 transitionName 也动态设置

_预期_
至于普通的 ImageViews(提供 scaleType 匹配),fragments 之间共享资源的无缝动画

_观察到_
SharedElementTransition 发生但在目标图像出现之前有闪烁(似乎目标图像设置得不够早)

_注意事项_
我曾尝试从 Web 和磁盘加载图像,并且在启动转换之前图像已加载并在缓存中。 目标片段的代码正在提取完全相同的 uri。 我尝试直接使用管道(并学到了很多东西)但未能影响结果。

_setup _
设备: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)

_Realisations _
在写这篇文章时,我注意到两件事可能相关:

  • 两个 Drawees _are_ 不同的尺寸(这对于转换标准 ImageViews 不是问题,我不记得任何关于设置目标尺寸的预取)
  • 从内存中我想我正在将 fresco 片段作为 Context 传递给代码中的某个地方,这可能意味着这两个片段每个都有自己的缓存?

@jorgemf - 您发布的代码不需要在 Activity 1 布局中设置匹配的 transitionName 属性吗? 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 不加载带有 attr“ android:transitionName ”的图像。 有人知道使用 Fresco 的外部解决方案吗?

@jorgemf如果您在 Activity1 Layout.xml 中设置了“android-background”,它的工作并不完美,但可以工作。
我在我的测试中设置它: android:background= "@ android:color/transparent "

@LuizGadao如果您设置背景,您将失去图书馆的所有优势。 我认为这是毫无意义的,因为您想要从互联网下载的图像。 不以静态资源为背景。
在测试了一些库之后,毕加索对我来说工作正常。 完全没有问题。

@jorgemf我同意你的看法。 这只是一个 hack 来做它的工作。

有这方面的消息吗?

@LuizGadao你能发布一个你的解决方法 XML 的例子吗?

感谢您报告此问题并感谢您的耐心等待。 我们已通知核心团队有关此问题的更新。 我们正在寻求在接下来的 30 天内回复,否则问题可能会被关闭。

有这方面的消息吗?

PS:
@goodev提供的

就像 boxcounter 所说的,Tra slateDraweeView 不适用于 HTC One M8,也不适用

如果您正在使用 ChangeImageTransform Transition,那么我认为共享元素转换失败,因为 ChangeImageTransform 正在为 ImageView 的 Matrix 设置动画,我认为它默认不支持 DraweeView。

我遇到的问题是共享元素以“fitCenter”开头,而最初是“centerCrop”。
项目可以复现问题
https://github.com/JackFan-Z/ActivitySharedElementTransition.git

虽然我添加了一个解决方法
它不适用于我使用 fresco 的另一个私人项目。
有人能找出真正的问题在哪里吗?

错误的转换开始状态
2015-10-01 11 26 34

过渡前
2015-10-01 11 26 50

@JackFan-Z
转换中的共享元素将最终视图设置为初始值并将其动画化为最终值。

普通 ImageView 结合ChangeImageTransform将捕获图像矩阵的开始和结束值,然后动画图像矩阵的变化。

但是DraweeView会覆盖与图像矩阵相关的某些函数,因此ChangeImageTransform不会对图像产生任何影响。

所以你最终得到的只是 ChangeBounds 生效。

目前,我发现没有办法操作 DraweeView 的图像矩阵。 甚至setActualImageMatrix也被标记为已弃用。 假设它没有被弃用,它的工作原理与默认 ImageView 的默认setImageMatrix完全一样。 即便如此,由于在设置DraweeViewHierarchy后您没有任何方法更改矩阵,因此对它的更改进行动画处理确实不是很方便。 所以你最终需要在每次onAnimationUpdate调用时创建一个新的DraweeViewHierarchy

我不知道为什么 DraweeView 以这种方式实现。 我认为当前可能的解决方案是取回底层位图并创建另一个 ImageView 来执行ChangeImageTransform转换。

@soapsign
谢谢你的评论。

实际上,在我的私人项目中,我确实尝试创建一个虚拟 ImageView,它采用与共享元素相同的位图。 问题仍然存在。
我不确定我面临的问题是否与壁画有关。
但是可以肯定的是,我可以使用 SimpleDraweeView 轻松重现相同的问题。

ChangeImageTransform使用内在维度来确定变换矩阵。 我们对DraweeView使用了DraweeHierarchy ,对于widthheight ,它的内在尺寸等于 -1。 这是因为Drawee已经应用了正确的比例类型缩放,因此视图不需要这样做。 此外, ImageView只能应用一种比例类型,而可绘制层次结构可以为每个图像分支(占位符、故障图像、实际图像等)使用单独的比例类型。 将实际的内在维度返回到视图只会增加大小错误的风险。
如果你想要过渡工作,你应该使用ChangeBounds

添加一个像“ fresco:ImageMatrixSrc=actual ”这样的新选项怎么样?

@boxcounter目前我们认为我们现在拥有的还可以。 但是您可以为您的提案创建一个拉取请求:)

@massimocarli ChangeBounds 仅当共享图像在两个活动/视图上具有相同大小时
你打算以这种方式做什么? ChangeImageTransform 解决了这个问题,但它在 DraweeView 中不起作用。

同样在这里...

@massimocarli ChangeBounds 不够好。

这就是我想要实现的(这是使用 ImageView): https :

这是使用 SimpleDraweeView 的样子: https :
请注意原始图像在动画图像后面错误地调整大小的方式。

这就是只有 ChangeBounds 作为过渡的样子: https ://gfycat.com/SorrowfulExemplaryAntlion

嘿伙计们,我有同样的问题。 ChangeBounds 工作不顺利。 如果有解决方法或修复方法,请告诉我们。 共享元素过渡是 Material Design 引入的最好的东西之一,而 fresco 是我迄今为止使用过的最好的库之一。 请让开发人员无缝使用两者。

有没有人能够找到解决方法,因为 Fresco 无法解决这个问题?

这是我使用的工作正常的解决方法:
https://github.com/bumptech/glide

大家好,

ChangeBounds 方法本身是不够的,我对 Facebook 的回答感到惊讶,即共享元素转换的当前状态还可以。

我终于找到了一个足够简单的解决方案,它似乎在示例项目中对我有用。
由于 ChangeBounds 转换不会通过 onMeasure() 而是通过 onSizeChanged() 更新布局本身,当前没有被任何 drawee 视图覆盖,因此在转换期间永远不会更新 drawable 的比例。

这是我们的 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我正在使用

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。 不推荐通过ChangeBoundssetReparenting(true)设置它,而建议使用ChangeTransform代替。 所以对于RecyclerViewtransitionSet.addTransition(new ChangeTransform());也是必需的。 (返回动画看起来仍然很糟糕,但至少进入动画是好的(除了缩放类型没有影响,createAnimator(...)中将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)。 为了使动画正常工作,我必须进行一些更改:

  • 通过transitionSet.addTransition(new ChangeTransform());ChangeTransform到过渡集

    • 这是因为ChangeBounds报告了RecyclerView起始视图的错误位置(它总是返回第一个元素的 X、Y 坐标)

  • createAnimator(...)if (mFromScale == mToScale) createAnimator(...)替换if (mFromScale == mToScale) if(mFromScale == mToScale && startBounds.equals(endBounds))

    • 如果两个 drawees 共享相同的比例类型,则转换不会发生,即使它们的大小不相同

  • 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工作)。
在支持库版本 v24.1.1 的 Android 5.0.2 上对此进行了测试。

请注意,如果您在具有相同大小的图像之间设置动画,则此解决方案将不起作用。

@Gericop这是一个可以正常工作的演示。 我刚刚提交到github上。 我试图最大程度地清理代码。 注意:我在回收器视图中只使用了 1 张图像,因为为了使 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。

编辑:您的演示仅测试默认的ChangeBoundsChangeTransform转换,而不是 Facebook 提供的DraweeTransition实现。

不幸的是,你是对的......我已经在我的设备上测试过它:
Android 5.0 + Fresco v0.11/v0.12 -> KO
Android 6.0 + Fresco v0.11/v0.12 -> OK
之前没注意...

@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 -> OK

@ladia12返回第一个活动时原图消失的问题是怎么解决的?

@dbrant我有同样的问题,你有没有找到解决的方法?

见#1446

@ladia12返回第一个活动时原图消失的问题是怎么解决的?

@ladia12返回第一个活动时原图消失的问题是怎么解决的? 我的原始图像在 recyclerview 的视图中

我最终使用 Picasso 进行共享元素转换。 这不是固定的
在壁画中。 所以毕加索是轻量级的,使用它没有任何问题
与壁画一起。

在星期三,2019年6月19日在下午5时11分bembem1011 [email protected]写道:

@ladia12 https://github.com/ladia12你是如何解决这个问题的
返回第一个活动时原始图像消失? 我的
原始图像在 recyclerview 的视图中


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/facebook/fresco/issues/22?email_source=notifications&email_token=AAXQ5WYUP5KBJYNBOZX7CCDP3ILM5A5CNFSM4A6ZMH32YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXWZZissue24000000000000000000000000000000000000000000000000
或静音线程
https://github.com/notifications/unsubscribe-auth/AAXQ5W5EXO5SV4R2PXVTG7LP3ILM5ANCNFSM4A6ZMH3Q
.

此页面是否有帮助?
0 / 5 - 0 等级