2011-10-10 22 views
34

Tôi có một ImageView với android:layout_width=100dp, android:layout_height=wrap_contentandroid:adjustViewBounds=trueadjustViewBounds ImageView không làm việc

Nó nguồn là một hình ảnh 50 x 50 px. Nhưng tỷ lệ khung hình không được bảo toàn - chiều cao của ImageView là 50px, không phải 100px (tức là adjustViewBounds không hoạt động). Nếu tôi có một hình ảnh 200x200px nó hoạt động - chiều rộng và chiều cao là 100px. Mã này kết quả trong một hình ảnh cao 100px rộng và 50px nhưng hình ảnh src là hình vuông:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 

    <ImageView 
     android:id="@+id/photo" 
     android:src="@drawable/icon" 
     android:layout_width="100dp" 
     android:layout_height="wrap_content" 
     android:scaleType="fitXY" 
     android:adjustViewBounds="true" /> 

</LinearLayout> 
+0

Điều đó thường hoạt động; bạn có thể cung cấp đoạn mã chính xác không? Ngoài ra cha mẹ của ImageView là gì? Có lẽ cha mẹ của nó đang buộc một kích thước nhất định, không cho phép ImageView thay đổi kích thước. –

+0

Tôi đã thêm mã. – fhucho

+0

Ah Tôi đã tìm thấy vấn đề, sẽ cung cấp câu trả lời ngay bây giờ. –

Trả lời

62

Vấn đề là adjustViewBoundssẽ không làm tăng kích thước của ImageView vượt quá kích thước tự nhiên của drawable. Nó sẽ chỉ thu hẹp chế độ xem để duy trì tỷ lệ khung hình; nếu bạn cung cấp hình ảnh 500x500 thay vì hình ảnh 50x50, điều này sẽ hoạt động.

Nếu bạn quan tâm đến vị trí mà hành vi này được triển khai, hãy xem ImageView.java's onMeasure implementation.

Một giải pháp thay thế là triển khai ImageView tùy chỉnh thay đổi hành vi này trong onMeasure.

+0

Bạn có biết thư viện nào sửa lỗi hành vi này của imageView không? –

+0

Liên kết không hoạt động được. – neworld

+0

đã sửa liên kết .. –

11

Có một cách đơn giản hơn. Hãy ImageView của bạn như thế này:

<ImageView 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:scaleType="fitCenter" 
    android:adjustViewBounds="true"/> 

Bằng cách này drawable sẽ căng khít tới ở trung tâm ImageView bằng cách gìn giữ tỉ lệ khung hình. Chúng tôi chỉ phải tính toán chiều cao đúng để làm cho nó tỷ lệ thuận với vì vậy chúng tôi không có bất kỳ chỗ trống:

private void setImageBitmap(Bitmap bitmap, ImageView imageView){ 
    float i = ((float)imageWidth)/((float)bitmap.getWidth()); 
    float imageHeight = i * (bitmap.getHeight()); 
    imageView.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth, (int) imageHeight)); 
    imageView.setImageBitmap(bitmap); 
} 
+1

Đây chỉ là một giải pháp tốt nếu căn chỉnh hình ảnh ở trung tâm của khung nhìn là những gì bạn muốn. Nếu bạn cần phải có một sự liên kết linh hoạt, xem Roman Nuriks câu trả lời và bình luận của tôi ở đó. – Nilzor

0

Tôi đã có một yêu cầu tương tự; trong trường hợp của tôi, tôi muốn hình ảnh là hình vuông và muốn ImageView khớp với tỷ lệ khung hình để tôi có thể sử dụng nền và phần đệm của nó để vẽ đường viền.

Tôi đã đọc câu trả lời ở đây nhưng thay vì ghi đè ImageView, tôi quyết định tạo Bố cục đảm bảo nội dung của nó (chỉ nên là một chế độ xem) là hình vuông. Bằng cách đó tôi có thể sử dụng một ImageView chuẩn bên trong nó. (Và bạn không bao giờ biết, tôi có thể muốn làm một cái gì đó khác sau này. Mặc dù có thể không.)

Trong trường hợp nó hữu ích cho bất cứ ai khác, đây là mã (cảm thấy tự do để sao chép). Có thể có lỗi như tôi vừa làm cho nó hoạt động cho ứng dụng của tôi sau đó dừng lại. :)

public class SquareLayout extends ViewGroup 
{ 
    public SquareLayout(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
    } 

    public SquareLayout(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    public SquareLayout(Context context) 
    { 
     super(context); 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) 
    { 
     // Work out width and height, and square size. 
     int width = r - l; 
     int height = b - t; 

     int size, xOffset, yOffset; 
     if(width < height) 
     { 
      size = width; 
      xOffset = 0; 
      yOffset = (height - size)/2; 
     } 
     else 
     { 
      size = height; 
      xOffset = (width - size)/2; 
      yOffset = 0; 
     } 

     for(int i = 0; i < getChildCount(); i++) 
     { 
      View child = getChildAt(i); 
      child.layout(xOffset, yOffset, size + xOffset, size + yOffset); 
     } 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     // Get width and height. 
     int w = -1, h = -1; 
     switch(MeasureSpec.getMode(widthMeasureSpec)) 
     { 
     case MeasureSpec.AT_MOST: 
     case MeasureSpec.EXACTLY: 
      w = MeasureSpec.getSize(widthMeasureSpec); 
      break; 

     case MeasureSpec.UNSPECIFIED: 
      break; 
     } 
     switch(MeasureSpec.getMode(heightMeasureSpec)) 
     { 
     case MeasureSpec.AT_MOST: 
     case MeasureSpec.EXACTLY: 
      h = MeasureSpec.getSize(heightMeasureSpec); 
      break; 

     case MeasureSpec.UNSPECIFIED: 
      break; 
     } 

     // If only one of width/height is unspecified, set them both the same. 
     if(w == -1 && h != -1) 
     { 
      w = h; 
     } 
     else if(h == -1 && w != -1) 
     { 
      h = w; 
     } 

     // Either they're both specified or both unspecified. 
     int childMeasureSpec; 
     if(w == -1) 
     { 
      childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
     } 
     else 
     { 
      childMeasureSpec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); 
     } 

     // Pass through to children. 
     int maxDimension = 1; 
     for(int i = 0; i < getChildCount(); i++) 
     { 
      View child = getChildAt(i); 
      child.measure(childMeasureSpec, childMeasureSpec); 
      maxDimension = Math.max(maxDimension, child.getMeasuredWidth()); 
      maxDimension = Math.max(maxDimension, child.getMeasuredHeight()); 
     } 

     if(w == -1) 
     { 
      w = maxDimension; 
      h = maxDimension; 
     } 

     setMeasuredDimension(w, h); 
    } 
} 
1

Ngoài @ của RomanNurik answer

Bạn có thể tìm giải pháp here làm việc, hoặc đang copy-paste hoặc chỉ cần thêm sự phụ thuộc Gradle

dependencies { 
    compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.1' 
} 

T.B. Giải pháp do @Nilzor cung cấp không hoạt động cho tôi

+0

Đối với người đọc tiếp theo, chế độ xem được gọi là 'com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView' – natinusala

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