带缩放类型centerCrop过渡的共享元素会跳动

当2个ImageViews从一个屏幕进入下一个屏幕时,我试图实现共享元素转换。 图像中的一个具有的scaleType centerCrop两个屏幕上。 我面临的问题是,当转换开始时,在将图像动画到下一个屏幕之前,图像将转换为原始大小(裁切之前)。 当它到达下一个屏幕时,它会以原始大小到达它,然后才会裁剪到目标图像视图。

整个经历并不顺利,真的让人眼前一亮。 我使用的代码是:

public void animateIntent(View view, ArticleCoverData articleCoverData) {
    Intent intent = new Intent(mActivity, ReaderActivity.class);
    intent.putExtra(Constants.ARTICLE_DATA, articleCoverData);

    // The view animation will start from
    View coverStartView = view.findViewById(R.id.coverImage);
    View coverDiagonalDecoratorStartView = view.findViewById(R.id.diagonal_image_decorator);

    Pair<View, String> pair1 = Pair.create(coverStartView, mActivity.getString(R.string.transition_timeline_cover_image_to_reader_name));
    Pair<View, String> pair2 = Pair.create(coverDiagonalDecoratorStartView, mActivity.getString(R.string.transition_timeline_cover_image_diagonal_decorator_to_reader_name));

    ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(mActivity, pair1, pair2);
    ActivityCompat.startActivity(mActivity, intent, options.toBundle());
}

使用Glide使用以下代码从网络加载图像:

Glide.with(mActivity).load(articleCoverData.mImageUrl).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.SOURCE).dontTransform().into(holder.coverImage);

在接收端,图像加载如下:

Glide.with(mContext).load(mData.mImageUrl).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(mCoverImageView);

在我定义的风格中:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Add this line -->
    <item name="android:windowContentTransitions">true</item>

    <!-- This is the color of the Status bar -->
    <item name="colorPrimaryDark">@color/transparent</item>

    <!-- specify shared element transitions -->
    <item name="android:windowSharedElementEnterTransition">
        @transition/change_image_transform</item>
    <item name="android:windowSharedElementExitTransition">
        @transition/change_image_transform</item>
</style>

change_image_transform是:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeImageTransform/>
</transitionSet>

编辑:试图改变过渡到:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeBounds/>
    <changeTransform/>
    <changeImageTransform/>
</transitionSet>

要么

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeBounds/>
    <changeImageTransform/>
</transitionSet>

但结果是一样的。

问题是:我在这里错过了些什么,有什么我需要做的,以使这种体验窒息? 或者这是一个Android错误?


最后,设法解决了这个问题。 使用以下代码和配置实现了期望的结果:

private static void startAnimatedTransitionIntent(Activity context, View view, ArticleCoverData articleCoverData) {
    Intent intent = new Intent(context, ReaderActivity.class);
    intent.putExtra(Constants.ARTICLE_DATA, articleCoverData);

    View coverStartView = view.findViewById(R.id.coverImage);
    View coverDiagonalDecoratorStartView = view.findViewById(R.id.diagonal_image_decorator);

    Window window = context.getWindow();
    View decor = window.getDecorView();
    View navigationBarStartView = decor.findViewById(android.R.id.navigationBarBackground);

    List<Pair<View, String>> pairs = new ArrayList<>();
    pairs.add(Pair.create(coverStartView, context.getString(R.string.transition_timeline_cover_image_to_reader_name)));
    pairs.add(Pair.create(coverDiagonalDecoratorStartView, context.getString(R.string.transition_timeline_cover_image_diagonal_decorator_to_reader_name)));

    if (navigationBarStartView != null) {
        pairs.add(Pair.create(navigationBarStartView, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME));
    }

    ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(context, pairs.toArray(new Pair[pairs.size()]));
    ActivityCompat.startActivity(context, intent, options.toBundle());
}

我使用Picasso和下面的代码将图像加载到图像视图中:

Picasso.with(mActivity).load(articleCoverData.mImageUrl).into(articleVH.coverImage);

在接收端,我以相同的方式应用图像:

Picasso.with(mContext).load(mData.mImageUrl).into(mCoverImageView);

样式:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:statusBarColor">@color/app_red</item>
    <item name="android:windowContentTransitions">true</item>

    <!-- This is the color of the Status bar -->
    <item name="colorPrimaryDark">@color/transparent</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>

    <!--<item name="android:windowEnterTransition">@transition/cheeses_enter</item>-->
    <!--<item name="android:windowExitTransition">@transition/cheeses_exit</item>-->

    <item name="android:windowSharedElementEnterTransition">@transition/cheeses_enter</item>
    <item name="android:windowSharedElementExitTransition">@transition/cheeses_exit</item>
</style>

两个转换: cheeses_entercheeses_exit是:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet>
    <changeBounds />
    <changeTransform />
    <changeClipBounds />
    <changeImageTransform />
</transitionSet>

重要的是使用ImageView scaleType参数应用您的比例类型,而不要使用Picasso裁切或Glide裁切。

因为如果你这样做,作物和非作物行动将作为过渡的一部分执行。


只是给任何人解答这个问题的答案(以及更多的解释)。

首先使用<changeImageTransform/><changeBounds/>足以完成转换。

问题主要是Glide如何处理图像视图/可绘制测量。 有一些延迟,因此没有创建过渡动画。

毕加索提供了足够快的图像位置值(矩阵)的基础上scaletype和转换工作。


我面临同样的问题,我已经在我的Glide加载请求中使用dontAnimate() + dontTransform()

对我而言,我的解决方案是删除

clipToPadding="false"
clipChildren="false"

从我的ImageView的容器ViewGroup。

在Shared元素转换期间使用scaleType="centerCrop"时,这些属性会使我的图像不被剪切。

链接地址: http://www.djcxy.com/p/92345.html

上一篇: Shared Element with scaleType centerCrop transition is jumpy

下一篇: Angular 2 component class methods confusion