2011-09-20 47 views
18

Tôi có hình ảnh nhỏ hơn vùng chứa mà tôi muốn nó vừa với bên trong. Tôi muốn hình ảnh giãn ra, giữ tỷ lệ khung hình của nó, với kích thước lớn nhất có thể.Cách tạo hình ảnh càng lớn càng tốt trong khi duy trì tỷ lệ khung hình

Để minh họa cho vấn đề này:

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

Các ImageView trên sẽ được kéo dài để điền vào chiều rộng của thùng sơn. Các @drawable nó chứa cũng sẽ kéo dài dọc theo trục x để phù hợp với chiều rộng của ImageView đó là hoàn hảo. Tuy nhiên, vấn đề là kích thước có nhãn wrap_content, trong trường hợp này chiều cao, vẫn giữ nguyên kích thước như chiều cao ban đầu của @drawable s.

Tôi đã đọc tài liệu về ScaleType here và không thể tìm thấy câu trả lời ở đó.

Những hình ảnh dưới đây mô tả mã trên:

enter image description hereenter image description here

Current behaviour    Desired Behaviour 

Sửa

Một ImageView cho scaleType="fitCenter" sẽ mở rộng một cách chính xác/thu nhỏ @drawable bên trong của nó để phát triển càng lớn càng tốt trong khi giữ lại ing tỷ lệ khung hình của nó.

Các kích thước ImageView s được xác định trước khi @drawable được chia tỷ lệ theo bất kỳ cách nào. Các kích thước ImageView không được thực hiện bằng cách mở rộng nó có chứa @drawable.

+2

Đối với tôi, đây là một vấn đề phổ biến, một vấn đề mà tôi chưa bao giờ tìm thấy một giải pháp sạch. Thêm vào nền 9 bản vá cho một khung và thậm chí còn tệ hơn khi thử và sửa chữa. Tôi khá chắc chắn đây là một cái gì đó bạn sẽ phải làm lập trình, nhưng nó sẽ được tốt đẹp nếu ai đó không có một giải pháp cho việc này. – kcoppock

+2

+1 cho câu hỏi được mô tả đầy đủ – Merlin

Trả lời

7

XML

Giải pháp duy nhất cho điều này trong XML là sử dụng "match_parent" hoặc một giá trị tối đa rời rạc thay vì "wrap_content" nếu có thể. Điều này sẽ đảm bảo rằng ImageView là kích thước chính xác, sau đó nghĩa là việc thêm scaleType="fitCenter" sẽ đảm bảo rằng @drawable sau đó sẽ được chia tỷ lệ chính xác.

Programatically

Nó xấu xí, nhưng bạn có thể thay đổi kích thước ImageView sau khi nó được kích thước đã được đưa ra các giá trị rời rạc:

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; 
      } 
     } 
    }); 

EDIT

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 để giải quyết sự cố thường gặp – Merlin

+0

Boolean 'changed' là gì? – BornToCode

+0

Vì vậy, trình lắng nghe onGlobalLayout không kích hoạt liên tục. Cũ hơn và khôn ngoan hơn, bây giờ tôi sẽ loại bỏ 'OnGlobalLayoutListener' khỏi' ViewTreeObserver' làm hành động đầu tiên trong phương thức 'onGlobalLayout()'. (Xem bản chỉnh sửa của tôi để biết chi tiết) – Graeme

1

Có vẻ như bạn muốn fitCenter, sử dụng Matrix.ScaleToFit CENTER.

+0

Tỷ lệ khung hình này giữ nguyên nhưng hình ảnh không được điền nữa.Điều này sẽ làm việc nếu chiều cao của ImageView là chính xác mà có thể được thực hiện theo chương trình nhưng tôi muốn nó xảy ra thông qua XML. – Graeme

+0

@Graeme - Từ liên kết: "Tính toán tỷ lệ sẽ duy trì tỷ lệ khung hình gốc src, nhưng cũng sẽ đảm bảo rằng src khớp hoàn toàn bên trong. * Ít nhất một trục (X hoặc Y) sẽ khớp chính xác. * Kết quả là tập trung bên trong dst. " - Mô tả của họ dường như ngụ ý rằng hình ảnh sẽ được kéo dài để lấp đầy chiều rộng hoặc chiều cao. Có lẽ nó chỉ co lại để vừa vặn, nhưng không căng ra sao? – mbeckish

+0

Mô tả đó chính xác - vì một trong các kích thước được đặt thành "wrap_content" tuy nhiên kích thước ban đầu của ImageView dường như xảy ra trước khi tỷ lệ, do đó chiều cao của Chế độ xem đã được đặt và đang sử dụng trục nhỏ nhất để vừa với , mà không phóng to nó. – Graeme

Các vấn đề liên quan