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

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

<ImageView
  android:layout_width="400px"
  android:layout_height="300px"
  android:scaleType="centerCrop" />

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

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

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

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

【问题讨论】:

标签: android android-layout imageview scaletype


【解决方案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);
    }
}

【讨论】:

【解决方案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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-25
      • 1970-01-01
      • 2016-09-08
      • 1970-01-01
      • 2017-06-07
      • 1970-01-01
      相关资源
      最近更新 更多