Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách load và hiển thị ảnh trong ImageView Android (Resource, Drawable, URI)

Giới thiệu

ImageView là View cơ bản để hiển thị ảnh. Bài viết trình bày các cách set ảnh: từ resource (drawable), từ URI/file, và best practices với Glide/Coil.

Các cách set ảnh vào ImageView

1. Từ Drawable Resource (XML)

<ImageView
    android:id="@+id/imageView"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:src="@drawable/ic_launcher_foreground"
    android:scaleType="centerCrop"
    android:contentDescription="Mô tả ảnh" />

2. Từ Drawable Resource (Code)

Java:

ImageView imageView = findViewById(R.id.imageView);
imageView.setImageResource(R.drawable.ic_launcher_foreground);

// Hoặc dùng Drawable (API 21+)
imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_launcher_foreground));

Kotlin:

binding.imageView.setImageResource(R.drawable.ic_launcher_foreground)
// Hoặc
binding.imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_launcher_foreground))

3. Từ File/URI (Internal Storage, Content Provider)

Java:

// Từ file path
File imgFile = new File("/storage/emulated/0/Pictures/photo.jpg");
if (imgFile.exists()) {
    Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
    imageView.setImageBitmap(bitmap);
}

// Từ Uri (content://...)
Uri imageUri = Uri.parse("content://media/external/images/media/123");
imageView.setImageURI(imageUri);

Kotlin:

// Từ file
val file = File("/storage/emulated/0/Pictures/photo.jpg")
if (file.exists()) {
    val bitmap = BitmapFactory.decodeFile(file.absolutePath)
    binding.imageView.setImageBitmap(bitmap)
}

// Từ Uri
val uri = Uri.parse("content://media/external/images/media/123")
binding.imageView.setImageURI(uri)

4. Từ Assets (assets/images/photo.jpg)

// Java
try (InputStream is = getAssets().open("images/photo.jpg")) {
    Drawable drawable = Drawable.createFromStream(is, null);
    imageView.setImageDrawable(drawable);
} catch (IOException e) {
    e.printStackTrace();
}

// Kotlin
try {
    val drawable = Drawable.createFromStream(assets.open("images/photo.jpg"), null)
    binding.imageView.setImageDrawable(drawable)
} catch (e: IOException) {
    e.printStackTrace()
}

Ví dụ hoàn chỉnh: Đổi ảnh khi click Button

Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp"
    android:gravity="center"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_foreground"
        android:contentDescription="Ảnh hiển thị" />

    <Button
        android:id="@+id/btnChangeImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="Đổi ảnh" />
</LinearLayout>

Code (MainActivity.kt)

package com.example.loadimageview

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.loadimageview.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private var currentImage = 0
    private val images = intArrayOf(
        R.drawable.img1,
        R.drawable.img2,
        R.drawable.img3,
        R.drawable.ic_launcher_foreground
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnChangeImage.setOnClickListener {
            currentImage = (currentImage + 1) % images.size
            binding.imageView.setImageResource(images[currentImage])
        }
    }
}

Best Practices: Dùng thư viện tải ảnh (Glide/Coil)

Đối với ảnh từ network, file lớn, hoặc danh sách (RecyclerView), không nên dùng setImageBitmap/setImageURI trực tiếp vì:

  • OOM (OutOfMemoryError) khi decode bitmap lớn.
  • Không có caching → tải lại nhiều lần.
  • Block UI thread khi decode.
  • Không handle placeholder/error state.

Với Glide:

Glide.with(this)
    .load(imageUrl) // String URL, Uri, File, Resource ID
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error_image)
    .centerCrop()
    .into(imageView)

Với Coil (Kotlin):

imageView.load(imageUrl) {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    error(R.drawable.error_image)
    transformations(CenterCropTransformation())
}

scaleType phổ biến

scaleTypeMô tả
centerCropCăn giữa, crop để lấp đầy (giữ tỷ lệ) - phổ biến nhất
centerInsideCăn giữa, scale down để vừa khung (không crop)
fitCenterScale để vừa khung, giữ tỷ lệ (có thể có khoảng trắng)
fitXYKéo dãn đầy khung (bị méo nếu tỷ lệ khác)
centerCăn giữa, không scale

Lưu ý quan trọng

  • Luôn set android:contentDescription cho accessibility (TalkBack).
  • Dùng android:adjustViewBounds="true" nếu muốn ImageView tự điều chỉnh bounds theo tỷ lệ ảnh.
  • Với bitmap lớn: dùng BitmapFactory.Options.inSampleSize hoặc thư viện load ảnh.
  • RecyclerView + ImageView: bắt buộc dùng Glide/Coil để tránh lag và OOM.