2011-09-20 93 views
18

我的图像比我希望装入的容器小。我希望图像能够伸展,保持纵横比,以达到最大可能的尺寸。如何在保持纵横比的同时尽可能大地制作图像

为了说明这个问题:

<ImageView android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:src="@drawable/thumbnail" 
      android:scaleType="fitXY" 
      android:adjustViewBounds="true"/> 

ImageView上述将被拉伸以填充所述容器的宽度。它包含的@drawable也将沿着x轴拉伸以适应完美的宽度ImageView。然而,问题在于,标记为wrap_content的尺寸(在此情况下为高度)保持与@drawable的初始高度相同。

我已阅读有关ScaleType here的文档,但无法在其中找到答案。

下面的图像描述了上面的代码:

enter image description hereenter image description here

Current behaviour    Desired Behaviour 

编辑

一种ImageView给出scaleType="fitCenter"将准确地扩大/收缩@drawable它里面生长尽可能大地保留它的宽高比。

ImageView s尺寸是在以任何方式缩放@drawable之前定义的。尺寸不受其包含的缩放影响@drawable

+2

对我来说,这是一个常见的问题,我从来没有找到一个干净的解决方案。为一个框架添加背景9补丁,更糟的是尝试修复。我非常肯定这是你必须以编程方式完成的事情,但如果有人有解决方案,这将是很好的。 – kcoppock

+2

对于一个完全描述的问题+1 + – Merlin

回答

7

XML

到这一点的唯一的解决方案在XML是使用"match_parent"或离散最大值代替"wrap_content"尽可能。这将确保ImageView是正确的大小,这将意味着添加scaleType="fitCenter"将确保@drawable然后将正确缩放。

编程方式

这是丑陋的,但它的尺寸已经给出离散值后,你可以调整的ImageView:

final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail); 

    ViewTreeObserver thumbnailViewVto = thumbnailView.getViewTreeObserver(); 
    thumbnailViewVto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     private boolean changed = false; 
     @Override 
     public void onGlobalLayout() { 
      if(!changed) { 
       Drawable image = getResources().getDrawable(R.drawable.thumbnail); 
       float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight(); 
       int height = thumbnailView.getHeight(); 

       thumbnailView.setLayoutParams(
         new LayoutParams(
           (int) (height * heighToWidthRatio), height)); 
       changed = true; 
      } 
     } 
    }); 

编辑

final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail); 

    thumbnailView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 

     @Override 
     public void onGlobalLayout() { 
      // Remove the GlobalOnLayout Listener so it only fires once. 
      thumbnailView.getViewTreeObserver().removeGlobalOnLayoutListener(this) 

      // Find the images Height to Width ratio 
      Drawable image = getResources().getDrawable(R.drawable.thumbnail); 
      float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight(); 

      // Use this ratio to discover the ratio of the ImageView to allow it to perfectly contain the image. 
      int height = thumbnailView.getHeight(); 
      thumbnailView.setLayoutParams(new LayoutParams(
           (int) (height * heighToWidthRatio), height)); 
     } 
    }); 
+1

+1解决常见问题 – Merlin

+0

什么是布尔'改变'为? – BornToCode

+0

这是因为onGlobalLayout监听器不会重复发射。老的和聪明的,我现在只需从'ViewTreeObserver'中删除'OnGlobalLayoutListener'作为'onGlobalLayout()'方法中的第一个动作。 (详见我的编辑) – Graeme

1

看起来你想要fitCenter,它使用 Matrix.ScaleToFit CENTER

+0

这保持了宽高比,但图像不再填充。如果ImageView的高度是正确的,这可以用编程方式完成,但我希望它通过XML发生。 – Graeme

+0

@Graeme - 从链接:“计算将保持原始src纵横比的比例,但也将确保src完全适合dst。*至少一个轴(X或Y)将完全适合。*结果是以dst为中心。“ - 他们的描述似乎暗示图像将被拉伸以填充宽度或高度。也许它只是缩小到适合,但不适合? – mbeckish

+0

该描述是完全正确的 - 因为其中一个维度被设置为“wrap_content”,但是ImageView的大小初始化似乎在缩放之前发生,因此View的高度已经设置,并且它正在使用最小的轴来适合,而不会扩大它。 – Graeme

相关问题