Android ImageView可缩放到固定高度,但裁剪过宽

Android ImageView可缩放到固定高度,但裁剪过宽,android,android-imageview,Android,Android Imageview,我希望我的客户能够以特定的方式进行缩放: 缩放,使图像的高度始终与ImageView 裁剪任何多余的宽度 一张图片比1000个单词更能说明问题,因此下面是我希望我的ImageView的表现。假设它有一个固定的高度,比如说100dp,假设它的宽度是match\u parent 注意 在手机布局上,图像高度被拉伸,但侧面被裁剪,类似于裁剪中心 在平板电脑布局上,图像也会拉伸以适应ImageView高度,其行为类似于fit\u CENTER 我怀疑我需要scaleType:matrix,但在

我希望我的客户能够以特定的方式进行缩放:

  • 缩放,使图像的高度始终与
    ImageView
  • 裁剪任何多余的宽度
一张图片比1000个单词更能说明问题,因此下面是我希望我的
ImageView
的表现。假设它有一个固定的高度,比如说100dp,假设它的宽度是
match\u parent

注意

  • 在手机布局上,图像高度被拉伸,但侧面被裁剪,类似于
    裁剪中心
  • 在平板电脑布局上,图像也会拉伸以适应
    ImageView
    高度,其行为类似于
    fit\u CENTER

我怀疑我需要
scaleType:matrix
,但在那之后我就迷路了。如何确保图像适合Y,但不适合X?

如果使用
scaleType:matrix
您需要创建自己的图像,并通过
setImageMatrix(matrix)
将其指定给视图,或者在自定义ImageView的测量方法中手动修改矩阵

public class MyImageView extends ImageView   {

 boolean done=false;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (done)
            return;

        final Drawable d = getDrawable();
        final int drawableW = d.getIntrinsicWidth();
        final int drawableH = d.getIntrinsicHeight();
        float ratio =  drawableW / drawableH;

        //int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        float scale=height/drawableH;

          Matrix m = getImageMatrix();

          float[] f = new float[9];
          m.getValues(f);

          f[Matrix.MSCALE_X]=scale;
          f[Matrix.MSCALE_Y]=scale;

          m.setValues(f);  

        done = true;

        requestLayout();

    }

}
LinearLayout ll=新的LinearLayout(本);
ll.设置方向(线性布局、垂直);
布局参数;
最终图像视图iv0=新图像视图(本);
//iv0.setBackgroundColor(0xffff0000);
params=新的layoutparms(layoutparms.MATCH_PARENT,100);
ll.addView(iv0,参数);
最终图像视图iv1=新图像视图(本);
//iv1.立根基色(0xff00ff00);
参数=新的布局参数(60100);
ll.addView(iv1,参数);
setContentView(ll);
Runnable action=new Runnable(){
@凌驾
公开募捐{
Drawable d=getResources().getDrawable(R.Drawable.layer0);
int dw=d.getIntrinsicWidth();
int dh=d.getIntrinsicHeight();
RectF src=新的RectF(0,0,dw,dh);
ImageView[]iviews={iv0,iv1};
for(int i=0;i
在我朋友卡洛斯·罗伯斯(Carlos Robles)和普斯金(pskink)的帮助下,我想出了以下自定义的
图像视图

public class FitYCropXImageView extends ImageView {
    boolean done = false;

    @SuppressWarnings("UnusedDeclaration")
    public FitYCropXImageView(Context context) {
        super(context);
        setScaleType(ScaleType.MATRIX);
    }

    @SuppressWarnings("UnusedDeclaration")
    public FitYCropXImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setScaleType(ScaleType.MATRIX);
    }

    @SuppressWarnings("UnusedDeclaration")
    public FitYCropXImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setScaleType(ScaleType.MATRIX);
    }

    private final RectF drawableRect = new RectF(0, 0, 0,0);
    private final RectF viewRect = new RectF(0, 0, 0,0);
    private final Matrix m = new Matrix();
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (done) {
            return;//Already fixed drawable scale
        }
        final Drawable d = getDrawable();
        if (d == null) {
            return;//No drawable to correct for
        }
        int viewHeight = getMeasuredHeight();
        int viewWidth = getMeasuredWidth();
        int drawableWidth = d.getIntrinsicWidth();
        int drawableHeight = d.getIntrinsicHeight();
        drawableRect.set(0, 0, drawableWidth, drawableHeight);//Represents the original image
        //Compute the left and right bounds for the scaled image
        float viewHalfWidth = viewWidth / 2;
        float scale = (float) viewHeight / (float) drawableHeight;
        float scaledWidth = drawableWidth * scale;
        float scaledHalfWidth = scaledWidth / 2;
        viewRect.set(viewHalfWidth - scaledHalfWidth, 0, viewHalfWidth + scaledHalfWidth, viewHeight);

        m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER /* This constant doesn't matter? */);
        setImageMatrix(m);

        done = true;

        requestLayout();
    }
}
在xml中,使用:

    android:scaleType="centerCrop"
    android:adjustViewBounds="true"


from&感谢:

您能否提供一个屏幕截图,说明您正在努力实现的目标?嗯。。。你不明白我的绘画创作吗?对不起,我不明白,请提供你的源代码,你的绘画创作已经足够好了,但这一个是伟大的@阿姆罗拉,你在开玩笑!是的,这就是为什么你要在onmeasure方法中调整高度。同样,你也可以改变宽度来保持比例,因为缩放类型是中心裁剪,如果宽度太大,它会被裁剪。如果你给我一秒钟,我会解释如何做到这一点。最后,我花了时间,写了一个矩阵解。我认为它在任何情况下都会很好的工作哇。。。没想到会变得这么低级。谢谢如果(完成)后,您可以检查它,如果不可绘制,则返回。系统将继续调用测量。此外,您还可以将此代码迁移到活动中,并在指定可绘制对象后进行所有计算。当然,功能不同,但逻辑是一样的。也许可以解释一下?如果在
ImageView
消息队列的末尾尚未设置可绘制文件,该怎么办?您所说的“如果尚未设置可绘制文件”是什么意思?您执行
iv.setImageDrawable(d)Runnable
中选择code>。如果可绘制文件是从internet异步获取的,并且您无法保证在获得该文件时会出现布局,反之,在布局出现时会出现可绘制文件,那么该怎么办?我使用Runnable只是因为我需要确保ImageView已经是布局,并且具有非零宽度和高度,如果ImageView的大小不是零(您也可以通过扩展ImageView并覆盖onSizeChanged来实现),您可以在任何时候指定图像可绘制。我认为Matrix.ScaleToFit.CENTER不起作用,它真的起作用吗?对我来说。。。我对
setRectToRect
方法没有深入的了解,但是if在我的设备上看起来不错!(就像拉伸一样)事实上,由于两个矩形具有相同的纵横比,任何ScaleToFit都会非常有效!它也适用于FitXCropYImageView,在填充宽度的同时交叉高度。您能告诉我要获得FitXCropYImageView需要做哪些更改吗?
    android:scaleType="centerCrop"
    android:adjustViewBounds="true"