如何确定由Glide加载到ImageView中的可绘制文件的最终边界?

问题描述 投票:0回答:1

我看了很多关于确定用Glide加载到Android ImageView中的图片大小的帖子,但它们似乎都是指ImageView的大小,或者源图片的原始大小。我需要能够找出ImageView内部的可绘制图像的BOUNDS是什么。

我使用的是Glide 4.11.0和Android系统,目标是API21+。我的布局非常简单。

        <ImageView
            android:id="@+id/media_image_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            app:srcCompat="@drawable/grandparents_grandchildren_translucent" />

在布局中定义了app:srcCompat值作为样本,在运行时这个ImageView有不同的图片由用户选择显示。这样做的代码也很直接。

            GlideApp.with(context)
                    .load(Uri.parse(path))
                    .apply(RequestOptions.fitCenterTransform())
                    .error(R.drawable.ic_image_error)
                    .into(imageView);

我没有选择指定一个 "硬编码 "的高度宽度,因为这个应用程序可以在许多不同的设备和密度上运行。我指望结合ImageViewGlide来适当地调整图片的大小以适应。

加载和查看都很好--但我需要知道运行这个应用程序的设备屏幕上的实际边界,而不仅仅是可绘制的图像。这是一个类似于 这个问题 从很多年前开始。

我在一个小的测试应用程序中(没有使用Glide),这个工作很好。在那段代码中,我只是使用与布局相关联的图像来进行推导可绘制边界的测试。我一直在做以下工作(在布局完成和ImageView加载图像之后)。

 RectF bounds = new RectF();
 Drawable drawable = mediaImageView.getDrawable();
 mediaImageView.getImageMatrix().mapRect(bounds, new RectF(drawable.getBounds()));

这是一张截图,我们自定义的绘图表面视图的onDraw()方法 经过调整后,覆盖在ImageView上,以绘制它 "认为 "代表可查看图像边界的矩形。

enter image description here

正如你所看到的 mediaImageView.getImageMatrix().mapRect() 方法正确地推导出了矩形,它代表了在ImageView中可见的drawable的边界,如绿色矩形所示。

当我移到使用Glide的 "真正的 "应用程序时,由 "Glide "方法推导出的值是由 mapRect() 的方法不再正确。我怀疑这是因为Glide在掩盖下所做的变换魔法以及它与ImageView的通信方式与上述推导最终可绘制边界的技术有某种程度的冲突。

enter image description here

我还通过调试器检查了当它进入代码时的可绘制边界矩形是什么,在这一关口,在这之前 mapRect() 的调用。在非Glide测试版本中,边界矩形与图像的原始尺寸相匹配(高4032像素,宽3024)。

在Glide版本中,可绘制的直角图的尺寸为 已调 (大概是Glide的)高1332像素,宽2000像素。我猜测这是Glide在暗中做的某种优化。然而,表面上看确实很奇怪,因为这个高度宽度A)绝对不是移动设备上的显示方式(如你在截图中看到的,它比宽高),B)与请求的变换(fitCenterTransform)的比例不匹配。然而,既然它显示正确,那么一定是有其他步骤参与其中,或者此时根本没有引用或使用可绘制的边界数据。

我如何才能获得可绘制的边界(而不仅仅是宽度和高度)?

android size drawable glide
1个回答
0
投票

我找到了一个变通的方法,感谢以下人士 此职位.

关键是在Glide流对drawable进行任何操作之前,但在它从网络中捕获它之后,拦截Glide流,并使用其固有的width-height作为计算变换后的边界的来源。

最后,我修改了用可绘制对象的边界初始化 "DrawView "的代码。这个改变包括以下步骤。

  1. 在Glide进行任何转换之前,获得正确的可绘制对象的宽度和高度。
  2. 使用矩阵转换手动计算可绘制的边界,该矩阵考虑了ImageView的宽度高度和它的比例类型(我们的总是FitCenter,所以使用的代码固定为使用该类型)。
  3. 使用得到的bounds来初始化我们的自定义 "drawView "视图。

幸运的是,我可以在Glide中使用一个RequestListener,在Glide从URL中抓取尺寸后,但在它执行 "进入 "ImageView之前抓取它。在这个监听器中,我可以执行与我所请求的转换方法相匹配的矩阵操作,以获得正确的边界。然后,我可以调用适当地初始化我们的DrawView自定义视图对象的方法。

       GlideApp.with(this)
                .load(Uri.parse(currentMedia.getUriPathToMedia()))
                .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) {
                        RectF visualizedDrawableRect = new RectF(); // left, top, right, bottom
                        Matrix m = new Matrix();
                        RectF srcDrawableRect = new RectF(0, 0, resource.getIntrinsicWidth(), resource.getIntrinsicHeight());
                        RectF imageViewRect = new RectF(0, 0, mediaImageView.getWidth(), mediaImageView.getHeight());
                        if ( m.setRectToRect(srcDrawableRect, imageViewRect, Matrix.ScaleToFit.CENTER) ) {
                            m.mapRect(visualizedDrawableRect,srcDrawableRect);

                            // INITIALIZE OUR DRAWVIEW HERE
                            initializeDrawView(visualizedDrawableRect);
                        }
                        return false;
                    }
                })
                .apply(RequestOptions.fitCenterTransform())
                .error(R.drawable.ic_image_error)
                .into(mediaImageView);

剩下的一个问题是,我是否需要担心以这种方式使用匿名监听器?我是否会招致内存泄漏?

© www.soinside.com 2019 - 2024. All rights reserved.