gpt4 book ai didi

Android - ImageView 的不同 scaleType 之间的共享元素转换未正确设置动画(使用 Glide)

转载 作者:行者123 更新时间:2023-12-03 20:53:46 26 4
gpt4 key购买 nike

请注意,这个问题与找到的问题非常相似 here .没有解决方案,所以我想我会提供一些代码并再次询问。

本质上,我正在尝试在两个 fragment 之间进行 ImageView 的共享元素转换。我的最终目标是制作一个看起来与默认图片库非常相似的动画。重要的一点是我正在使用 Glide 来加载我的图像。我遇到的问题是 我无法让 scaleType 平滑地制作动画(从 centerCrop 到 fitCenter)。

我有一个包含 RecyclerView 的 fragment ,每个 fragment 都包含一个 ImageView。这些 ImageView 是缩略图,XML 看起来像这样:

<ImageView
android:id="@+id/ivPhoto"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/large_spacing"
android:scaleType="centerCrop"/>

重要/有问题的部分是 scaleType="centerCrop"
我使用以下方法设置转换名称并在我的 RecyclerView 适配器中加载图像:
holder.ivPhoto.setTransitionName(current.getPhotoFilepath());
Glide.with(holder.ivPhoto.getContext())
.load(current.getPhotoFilepath())
.dontTransform()
.into(holder.ivPhoto);

单击某个项目时,将运行以下代码:
@Override
public void onItemClicked(AssetDetail assetDetail, ImageView imageView) {
if (assetDetail.getPhotoFilepath() != null) {
AssetDetailFragmentDirections.ActionAssetDetailFragmentToDisplayImageFragment action = AssetDetailFragmentDirections.actionAssetDetailFragmentToDisplayImageFragment(assetDetail.getPhotoFilepath());
FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder()
.addSharedElement(imageView, assetDetail.getPhotoFilepath())
.build();
NavHostFragment.findNavController(this).navigate(action, extras);
}
}

这会将您带到第二个 fragment ,它基本上只包含以下 ImageView(技术上是 PhotoView,我也尝试过使用普通的 ImageView):
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />

我推迟了输入转换并设置了我想使用的转换:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
postponeEnterTransition();
TransitionSet transitionSet = new TransitionSet()
.addTransition(new ChangeBounds())
.addTransition(new ChangeImageTransform())
.setDuration(1500)
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.setInterpolator(new FastOutSlowInInterpolator());
setSharedElementEnterTransition(transitionSet);
}

最后我得到 & 设置过渡名称,加载图像并启动推迟的输入过渡:
DisplayImageFragmentArgs args = DisplayImageFragmentArgs.fromBundle(getArguments());
binding.ivImage.setTransitionName(args.getImageFilepath());

Glide.with(requireContext())
.load(args.getImageFilepath())
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
startPostponedEnterTransition();
return false;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
startPostponedEnterTransition();
return false;
}
})
.dontTransform()
.into(binding.ivImage);

这导致 this animation这是完全错误的。

如果我像这样交换转换的顺序:
TransitionSet transitionSet = new TransitionSet()
.addTransition(new ChangeImageTransform())
.addTransition(new ChangeBounds())
.setDuration(1500)
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.setInterpolator(new FastOutSlowInInterpolator());

我得到 this animation哪个更近,但进入转换从一个奇怪的地方开始,返回转换在持有 ImageView 的 CardView 后面/内部。

尝试一些不同的转换(根据 this article )
TransitionSet transitionSet = new TransitionSet()
.addTransition(new ChangeClipBounds())
.addTransition(new ChangeTransform())
.addTransition(new ChangeBounds())
.setDuration(1500)
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.setInterpolator(new FastOutSlowInInterpolator());

结果 this .在这一个中,您可以看到 scaleType 立即更改,然后动画的其余部分发生。我希望 scaleType 更改与其他所有内容一起平滑动画。

转换的最终组合的一个有趣点是,如果我删除 scaleType="centerCrop"从 RecyclerView 中的 ImageView 它可以完美地动画,但显然这意味着图像具有其原始纵横比并且不是正确的缩略图。见 here .

这个问题显然与 scaleType 有关,但无论我尝试什么,我似乎都无法让它工作。我已经进行了大量的谷歌搜索和阅读,但没有找到解决问题的方法。

据我了解,使用 ChangeImageTransform 应该为 scaleType 设置动画,但是将它与我​​尝试过的任何组合一起使用(这里列出的更多,包括与 ChangeTransform 一起尝试)似乎不起作用,或者至少不完全是我想要/期望的方式。在这一点上,我感到非常沮丧。

如果有人可以帮助我解决这个问题,我将不胜感激。

最佳答案

作为 Shared Element with scaleType centerCrop transition is jumpy 的提问者,最简单的解决方案可能是切换到 Picasso 而不是 Glide。最后做了。
问题在于 Glide 调整图像大小以适应每个 ImageView 以节省内存的方式。如果缩略图 ImageView 大小与 ViewPager 大小不同,它会破坏共享元素转换的 ChangeImageTransform。
首先,您的过渡集应包含:

<changeClipBounds/>
<changeTransform/>
<changeBounds/>
<changeImageTransform/>
关键是添加到 Glide 请求中:
.dontTransform()
.override(screenWidth, screenHeight)
但是,这将导致 Grid fragment 中的内存使用率很高,因为每个图像将以比缩略图所需的大得多的大小加载。您将体验到缓慢的滚动和崩溃。
因此,您可以默认以旧方式加载图像,然后在转换之前加载全屏大小的图像,单击网格项。您还需要推迟 Pager fragment 事务直到加载完整图像,以便转换可以快照新的 ImageView 属性。
onClickGridItem() {
Glide.with(imageView)
.load(uri)
.listener(RequestListener<Drawable> {
onResourceReady() {
openPagerFragment()
return false
}
})
.dontTransform()
.override(screenWidth, screenHeight)
.into(imageView)
}
这可能会导致在图像尺寸之间交换时出现不必要的闪烁。您可以通过在将其设置为 ImageView 之前预加载全尺寸图像来避免这种情况:
Glide.with(imageView)
.load(uri)
.listener(RequestListener<Drawable> {
onResourceReady() {
Glide.with ... .override(screenWidth, screenHeight).into(imageView)
return false
}
})
.dontTransform()
.preload(screenWidth, screenHeight)

关于Android - ImageView 的不同 scaleType 之间的共享元素转换未正确设置动画(使用 Glide),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61755467/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com