在Android 5.0中转换ImageView时出现问题

9
我在Android 5.0中遇到了一个关于ImageView在Activity之间过渡的奇怪问题/bug。 我试图将来自Activity A中Fragment A的缩略图映射到Activity B中Fragment B的头像上。大多数时间它表现良好,但有时会稍微出现问题。 以下是出现问题时的图片: https://istack.dev59.com/Wt248.webp 理应填满整个区域。两个ImageView的ScaleType都设置为CENTER_CROP,所以我无法想象这是否为问题所在。
值得注意的是,当在Activity B中滚动时(所有内容都包含在自定义ScrollView中,在滚动时更改ImageView的填充),问题会立即解决。
启动Activity B的代码非常简单:
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
    activity, thumbImageView, "cover"); // "cover" is the shared element name for both ImageViews
ActivityCompat.startActivity(activity, intent, options.toBundle());

这里是ScrollView可观察监听器的代码:
scrollview.setOnScrollChangedListener(new OnScrollChangedListener() {
    @Override
    public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {
        // Such parallax, much wow
        headerImageView.setPadding(0, (int) (t / 1.5), 0, 0);
    }
});

此外,这是我主题风格的一部分:
<item name="android:windowContentTransitions">true</item>
<item name="android:windowAllowEnterTransitionOverlap">true</item>
<item name="android:windowAllowReturnTransitionOverlap">true</item>
<item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
<item name="android:windowSharedElementExitTransition">@android:transition/move</item>

有什么想法吗?

你在使用哪些转换? - klmprt
抱歉,我忘了提到。这是默认的 @android:transition/move 过渡效果。 - Michell Bak
这个 bug 发生的频率有多高(例如每次、随机等)?此外,如果您在滚动视图监听器中注释掉 setPadding() 代码,该 bug 是否仍然存在?我只是想了解为什么会出现这种情况的根本原因。 - Alex Lockwood
@AlexLockwood 看起来很随机,但我会说它发生的概率约为25%。是的,如果我注释掉 setPadding(),它就会出现这种情况,但如果我这样做,当我滚动时它不会自动修复。它只会保持错误状态。 - Michell Bak
1个回答

4
尝试将以下代码添加到您的Fragment B的onCreateView()方法中:
请注意,该段代码涉及IT技术。
getActivity().postponeEnterTransition(); 
scrollView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
    public boolean onPreDraw() { 
        scrollView.getViewTreeObserver().removeOnPreDrawListener(this);
        getActivity().startPostponedEnterTransition();
        return true;
    }
});

这段代码存在时,该问题是否仍然存在?这将确保过渡仅在片段完成其布局后才开始。
您甚至可能需要在此之后调用 startPostponedEnterTransition()...例如,如果您在第二个活动中加载高分辨率图像,请在图像加载后调用startPostponedEnterTransition(即在ImageView上设置onPreDraw监听器而不是在窗口的装饰视图上)。

很遗憾,这种情况仍然发生。看起来缩略图 ImageView 在 Activity B 中过渡时没有改变其边界到更宽的 ImageView 边界。 - Michell Bak
1
你可能需要在Activity的onCreate()方法中调用postponeEnterTransition。 - George Mount
2
@GeorgeMount 如果我说错了,请纠正我,但我相信处理加载缓慢的高分辨率图像的一种方法是利用框架在转换开始之前对共享元素进行的“快照”。如果您调用 Activity#setEnterSharedElementCallback() 然后覆盖 onSharedElementStart(),第三个参数将为您提供一个“快照视图”列表,如果高分辨率图像尚未加载,则可以在过渡期间用作占位符。我从未亲自测试过这一点,但只是想让您知道它的存在。 - Alex Lockwood
@tir38,你能否分享一段示例代码或者你是如何实现的?那个快照视图是在下载视图之前放置的吗?还是图片缓存?你使用了哪些过渡效果?我在这里提出了一个问题:http://stackoverflow.com/questions/35846447/android-sharedelementtransition-imageview-not-moving-properly - Jemshit Iskenderov
@JemshitIskenderov 那不是我的应用程序,所以我没有任何源代码。 - tir38
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接