Search…

scaleType của ImageView trong Android

Nguyễn NghĩaNguyễn Nghĩa
16/11/20207 min read
scaleType là thuộc tính xác định cách thức mà hình ảnh được scale như thế nào để phù hợp với View, ImageView có thể hiển thị hình ảnh theo nhiều cách khác nhau, phụ thuộc vào các giá trị của thuộc tính scaleType.

Giới thiệu

Hầu hết các ứng dụng, web, game trên desktop, web, mobile đều sử dụng hình ảnh, trong Android để hiển thị hình ảnh, ImageView được dựng sẵn trong Android SDK hỗ trợ rất tốt điều này, ImageView là 1 View có chức năng tải, và hiển thị hình ảnh, hoặc bất cứ drawable. ImageView xử lý tất cả các công việc để hiển thị hình ảnh.

scaleType của ImageView có ý nghĩa như thế nào?

scaleType là thuộc tính xác định cách thức mà hình ảnh được scale như thế nào để phù hợp với View. ImageView có thể hiển thị hình ảnh theo nhiều cách khác nhau, phụ thuộc vào các giá trị của thuộc tính scaleType.

Giả sử 1 ImageView có kích thước là width = 100px, height = 100px và hình ảnh có kích thước là 400x500.

<ImageView
   android:scaleType="fitXY"
   android:src="@drawable/my_image"
   android:layout_width="100px"
   android:layout_height="100px" />

Khi cài đặt scaleType="fitXY", có nghĩa là hình ảnh sẽ được scale về kích thước đúng bằng với kích thước của View là 100x100. Kết quả là hình ảnh phù hợp đúng với View nhưng hình ảnh không còn giữ được tỉ lệ của nó nữa.

ImageView có các scaleType dưới đây như sau:

  • fitXY
  • fitCenter
  • fitStart
  • fitEnd
  • matrix
  • center
  • centerCrop
  • centerInside

Giá trị mặc định scaleType của ImageView

Khởi tạo ImageView bằng XML hoặc bằng mã Java và không đặt giá trị scaleType, lúc đó giá trị mặc định của scaleType sẽ là FIT_CENTER.

Các giá trị scaleType và ý nghĩa

Ý nghĩa các giá trị scaleType của ImageView được mô tả chi tiết ở bảng dưới đây:

ScaleType Mô tả
fitXY Scale hai chiều x, y của hình ảnh bằng đúng kích thước của View mà không quan tâm đến tỷ lệ của hình ảnh.
fitCenter Scale hình ảnh sao cho fit hình ảnh trong View và giữ nguyên tỷ lệ của hình ảnh. Có ít nhất 1 chiều (x hoặc y) sẽ bằng đúng kích thước (width, height) của View và hiển thị hình ảnh ở giữa (center). Ví dụ như hình ảnh landscape (hình ảnh ngang) thì chiều rộng hình ảnh sẽ được scale cho cho bằng với chiều rộng của View.
fitStart Giống với fitCenter nhưng hình ảnh sẽ hiển thi ở phía top-left của View.
fitEnd Giống với fitCenter nhưng hình ảnh sẽ được hiển thị ở phía bottom-right của View
matrix Scale hình ảnh dựa vào matrix, matrix được apply sử dụng phương thức setImageMatrix.
center Scale hiển thị hình ảnh ở chính giữa View.
centerCrop

Scale hình ảnh cả hai chiều x và y lớn hơn hoặc bằng kích thước của View trong khi vẫn giữ tỷ lệ của hình ảnh và hiển thị hình ảnh ở chính giữa View.

centerInside Scale hình ảnh cả hai chiều x và y nhỏ hơn hoặc bằng kích thước của View trong khi vẫn giữ tỷ lệ của hình ảnh và hiển thị hình ảnh ở chính giữa View.

Dưới đây là hình ảnh được hiển thị với ImageView sử dụng các ScaleType khác nhau:

Và dưới đây là đoạn mã xử lý scaleType của ImageView:

private void configureBounds() {
  if (mDrawable == null || !mHaveFrame)
      return;

  final int dwidth = mDrawableWidth;
  final int dheight = mDrawableHeight;
  final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
  final int vheight = getHeight() - mPaddingTop - mPaddingBottom;
  final boolean fits = (dwidth < 0 || vwidth == dwidth) && (dheight < 0 || vheight == dheight);

  if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
      /* If the drawable has no intrinsic size, or we're told to
          scaletofit, then we just fill our entire view.
      */
      mDrawable.setBounds(0, 0, vwidth, vheight);
      mDrawMatrix = null;
  } else {
      // We need to do the scaling ourself, so have the drawable
      // use its native size.
      mDrawable.setBounds(0, 0, dwidth, dheight);
      if (ScaleType.MATRIX == mScaleType) {
          // Use the specified matrix as-is.
          if (mMatrix.isIdentity())
              mDrawMatrix = null;
          else
              mDrawMatrix = mMatrix;
      } else if (fits) {
          // The bitmap fits exactly, no transform needed.
          mDrawMatrix = null;
      } else if (ScaleType.CENTER == mScaleType) {
          // Center bitmap in view, no scaling.
          mDrawMatrix = mMatrix;
          mDrawMatrix.setTranslate(Math.round((vwidth - dwidth) * 0.5f),
                                   Math.round((vheight - dheight) * 0.5f));
      } else if (ScaleType.CENTER_CROP == mScaleType) {
          mDrawMatrix = mMatrix;

          float scale;
          float dx = 0, dy = 0;

          if (dwidth * vheight > vwidth * dheight) {
              scale = (float)vheight/(float) dheight;
              dx = (vwidth - dwidth * scale) * 0.5f;
          } else {
              scale = (float)vwidth/(float)dwidth;
              dy = (vheight - dheight * scale) * 0.5f;
          }
          mDrawMatrix.setScale(scale, scale);
          mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));
      } else if (ScaleType.CENTER_INSIDE == mScaleType) {
          mDrawMatrix = mMatrix;
          float scale;
          float dx;
          float dy;

          if (dwidth <= vwidth && dheight <= vheight)
              scale = 1.0f;
          else
              scale = Math.min((float)vwidth/(float)dwidth, (float)vheight/(float)dheight);

          dx = Math.round((vwidth - dwidth * scale) * 0.5f);
          dy = Math.round((vheight - dheight * scale) * 0.5f);

          mDrawMatrix.setScale(scale, scale);
          mDrawMatrix.postTranslate(dx, dy);
      } else {
          // Generate the required transform.
          mTempSrc.set(0, 0, dwidth, dheight);
          mTempDst.set(0, 0, vwidth, vheight);

          mDrawMatrix = mMatrix;
          mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
      }
  }
}

Scale Bitmap

Scale 1 hình ảnh trong Android như sau:

// Load a bitmap from the drawable folder
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
// Resize the bitmap to 150x100 (width x height)
Bitmap bMapScaled = Bitmap.createScaledBitmap(bMap, 150, 100, true);
// Loads the resized Bitmap into an ImageView
ImageView image = (ImageView) findViewById(R.id.test_image);
image.setImageBitmap(bMapScaled);

Phương thức createScaledBitmap() sử dụng để scale Bitmap với các đối số truyền vào là width, heightfilter.

Nếu muốn scale hình ảnh mà vẫn giữ tỷ lệ thì sử dụng lớp sau:

public class BitmapScaler {
    // Scale and maintain aspect ratio given a desired width
    // BitmapScaler.scaleToFitWidth(bitmap, 100);
    public static Bitmap scaleToFitWidth(Bitmap b, int width)
    {
      float factor = width/(float)b.getWidth();
      return Bitmap.createScaledBitmap(b, width, (int)(b.getHeight() * factor), true);
  }
    // Scale and maintain aspect ratio given a desired height
    // BitmapScaler.scaleToFitHeight(bitmap, 100);
    public static Bitmap scaleToFitHeight(Bitmap b, int height)
    {
      float factor = height/(float)b.getHeight();
      return Bitmap.createScaledBitmap(b, (int)(b.getWidth() * factor), height, true);
  }
    // ...
}

Tham khảo

https://guides.codepath.com/android/Working-with-the-ImageView#scale-types

IO Stream

IO Stream Co., Ltd

developer@iostream.co
383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2025