【问题标题】:Android Glide library not working with shared element transitionsAndroid Glide 库不适用于共享元素转换
【发布时间】:2015-06-18 18:51:48
【问题描述】:

我希望采用Glide library 代替Universal Image Loader,但在共享元素转换方面遇到了问题。

在我的简单沙盒中,我使用 UIL 创建了以下转换:https://dl.dropboxusercontent.com/u/97787025/device-2015-06-18-113333.mp4

很简单,而且效果很好。但是当我使用 Glide 时,它​​看起来并不那么好:https://dl.dropboxusercontent.com/u/97787025/device-2015-06-18-114508.mp4

这是我正在使用的代码

第一个活动:

public class MainActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        final ImageView iv = (ImageView) findViewById(R.id.main_image);

        displayImageGlide(BaseActivity.IMAGE_URL, iv, true);

        Button button = (Button) findViewById(R.id.main_button);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), DifferentActivity.class);
                startActivity(intent, iv);
            }

        });
    }

}

第二个:

public class DifferentActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        setContentView(R.layout.different);

        ImageView imageView = (ImageView) findViewById(R.id.diff_image);

        displayImageGlide(BaseActivity.IMAGE_URL, imageView, false);
    }

}

BaseActivity 只包含displayImageGlide

public void displayImageGlide(String url, ImageView imageView) {
    Glide.with(this).load(url)
            .asBitmap().transform(new CustomTransformation(this))
            .skipMemoryCache(true)
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .into(imageView);
}

private static class CustomTransformation extends BitmapTransformation {

    public CustomTransformation(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return bitmapChanger(toTransform, outWidth, outHeight);
    }

    @Override
    public String getId() {
        return "some_id_1";
    }

}

private static Bitmap bitmapChanger(Bitmap bitmap, int desiredWidth, int desiredHeight) {
    float originalWidth = bitmap.getWidth();
    float originalHeight = bitmap.getHeight();

    float scaleX = desiredWidth / originalWidth;
    float scaleY = desiredHeight / originalHeight;

    //Use the larger of the two scales to maintain aspect ratio
    float scale = Math.max(scaleX, scaleY);

    Matrix matrix = new Matrix();

    matrix.setScale(scale, scale);

    //If the scaleY is greater, we need to center the image
    if(scaleX < scaleY) {
        float tx = (scale * originalWidth - desiredWidth) / 2f;
        matrix.postTranslate(-tx, 0f);
    }

    Bitmap result = Bitmap.createBitmap(desiredWidth, desiredHeight, bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(bitmap, matrix, new Paint());
    return result;
}

我尝试从 Glide 构建器中删除缓存行(用于防止它缓存我正在尝试调整的内容),但这并没有帮助。很想采用 Glide,但如果这行不通,那就是一个交易破坏者。如果有人有任何意见,我将不胜感激,谢谢!

【问题讨论】:

  • 没有使用过 Glide 但我猜转换会动态切换图像,这会导致动画过程中出现卡顿。在 ImageView 上设置 android:scaleType="centerCrop" 不会解决问题吗?
  • centerCrop 不是我想要的比例类型,但 CustomTransformation 方法将自定义矩阵应用于位图,从而生成非常适合边界的图像。

标签: android android-glide


【解决方案1】:

我尝试了您的代码并得到了相同的结果,然后我尝试了另一个实现:https://github.com/codepath/android_guides/wiki/Shared-Element-Activity-Transition

并进行了一些更改,我认为这是这里的关键:

centerCrop 应该在 ImageView 上设置,如果我们用 Glide 设置它会导致同样的错误。 activity_main.xml

    <ImageView
      android:id="@+id/ImageView"
      android:layout_width="match_parent"
      android:layout_height="150dp"
      android:layout_centerInParent="true"
      android:transitionName="detail_image"
      android:scaleType="centerCrop"
    />

BaseActivity.java 在 MainActivity 上 dontTransform 应该为 true,在 DifferentActivity 上为 false。

    public void displayImageGlide(String url, ImageView imageView, Boolean dontTransform) {
    if (dontTransform) {
        Glide.with(this).load(url)
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .dontTransform()
                .into(imageView);
        return;
    }

        Glide.with(this).load(url)
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .into(imageView);
   }

编辑,看看它的样子: https://www.dropbox.com/s/30s5l8awxogltls/device-2015-06-23-153153.mp4?dl=0

【讨论】:

  • 这个响应的问题是它没有使用我希望我的图像使用的顶部居中矩阵。
  • 我也遇到了同样的问题,能否提供完整的实现?谢谢!
  • 这里的解决方案仅适用于从裁剪缩略图到全尺寸图像的图像。如果您的原始图像很高,那么 centercrop 最终会拉伸它,这会导致后面的动画看起来很糟糕。
【解决方案2】:

对于那些在使用 Glide 的 SharedElementTransition 中苦苦挣扎的人,我想我找到了一个可行的解决方法,或者至少它对我有用。在您的第二个活动或片段中使用此代码:

postponeEnterTransition();
GlideApp.with(this)
        .load(imageToLoad)
        .listener(new RequestListener<Drawable>() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                return false;
            }

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

如果您的目标是 API

supportPostponeEnterTransition();
supportStartPostponedEnterTransition();

希望有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    相关资源
    最近更新 更多