你如何缩放像 centerCrop 这样的 ImageView,但是从顶部开始?

Posted

技术标签:

【中文标题】你如何缩放像 centerCrop 这样的 ImageView,但是从顶部开始?【英文标题】:How do you scale an ImageView like centerCrop, but from top? 【发布时间】:2016-07-07 02:37:53 【问题描述】:

假设我从 API 获取一些图像。我不知道图像的尺寸会提前是多少,但我知道我希望该图像成为ImageViewsrc,我已设置为某个特定大小。我希望从 API 获得的任何图像都填充整个ImageView,我想保持纵横比,并且我不在乎一个维度(宽度或高度)是否对于视图的设置大小来说太大了——所以我用centerCrop

<ImageView
  android:layout_
  android:layout_
  android:scaleType="centerCrop" />

如果从 API 返回的图像是这样的:

当它被设置为ImageView 的src 时,结果将类似于此(阴影部分被剪掉):

但是,我收到一个要求,我们应该始终显示图像的顶部并从下向上裁剪。所以想要的结果是这样的:

我确信这是可能的,但我是一个在他的联盟之外经营的网络人。以某种方式扩展ImageView,或者尝试scaleType="matrix"setImageMatrix(),或者第三个未提及的选项会更好吗?

【问题讨论】:

可能重复***.com/questions/6330084/imageview-scaling-top-crop How set imageview scaletype to topCrop的可能重复 【参考方案1】:

使用这个TopCropImageView gist

import android.content.Context;
import android.graphics.Matrix;
import android.widget.ImageView;

/**
* ImageView to display top-crop scale of an image view.
*
* @author Chris Arriola
*/
public class TopCropImageView extends ImageView 

    public TopCropImageView(Context context) 
        super(context);
        setScaleType(ScaleType.MATRIX);
    

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
        super.onLayout(changed, left, top, right, bottom);
        recomputeImgMatrix();
    

    @Override
    protected boolean setFrame(int l, int t, int r, int b) 
        recomputeImgMatrix();
        return super.setFrame(l, t, r, b);
          

    private void recomputeImgMatrix() 
        final Matrix matrix = getImageMatrix();

        float scale;
        final int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        final int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom();
        final int drawableWidth = getDrawable().getIntrinsicWidth();
        final int drawableHeight = getDrawable().getIntrinsicHeight();

        if (drawableWidth * viewHeight > drawableHeight * viewWidth) 
            scale = (float) viewHeight / (float) drawableHeight;
         else 
            scale = (float) viewWidth / (float) drawableWidth;
        

        matrix.setScale(scale, scale);
        setImageMatrix(matrix);
    

【讨论】:

我还在你的 gist 中添加了这个类的 Kotlin 版本:gist.github.com/arriolac/3843346#gistcomment-3604153【参考方案2】:

如果您使用 Glide,则可以使用自定义转换。随意使用我的(这是 Glide 的 CenterCrop 类的几乎完全相同的副本),它需要百分比:

https://gist.github.com/bjornson/3ff8888c09908d5c6cc345d0a8e1f6a7

像任何其他位图转换一样使用它:

Glide.with(getContext())
    .load(imagePath)
    .transform(new PositionedCropTransformation(getContext(), 1, 0))
    .into(imageView);

常用值: 左上方: 0, 0 右上: 0, 1 左下方: 1, 0 右下角: 1, 1

使用 0.5f 作为中心

【讨论】:

这不适用于 Glide 4.x。我插入的所有值都向右裁剪【参考方案3】:

PositionedCropTransformation 转换代码以支持 Glide v4.x https://gist.github.com/bjornson/3ff8888c09908d5c6cc345d0a8e1f6a7

【讨论】:

【参考方案4】:

如果你使用 Glide,你可以通过这种方式使用 optionalTransform:

Glide.with(context).load("http:///...")
            .override(300, 300)
            .optionalTransform(
                  new Transformation<Bitmap>() 
                     @NonNull
                     @Override
                     public Resource<Bitmap> transform(@NonNull Context context, 
                    @NonNull Resource<Bitmap> resource, int outWidth, int outHeight) 
                                       resource.get().setHeight(YOUR_CUSTOM_HIGHT);
                                       return resource;
                                   

                    @Override 
                    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) 

                                   
                               

            )
           into(binding.img);

【讨论】:

以上是关于你如何缩放像 centerCrop 这样的 ImageView,但是从顶部开始?的主要内容,如果未能解决你的问题,请参考以下文章

Android 在 centerCropped 图像中创建一个圆孔

如何像imageview一样裁剪位图中心? [复制]

如何获得图像的缩放功能?

颤动,滚动,捏合和缩放大图像

使用自动布局缩放垂直约束

ImageView