2011-09-20 48 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

相關問題