Flutter: Resim Eklemek - Assets ve Image.asset
Son güncelleme:
6 dk okuma

Flutter'da projenize resim eklemek için önce resimleri bir klasöre yerleştirmeniz ve ardından pubspec.yaml dosyasında bunları asset olarak tanımlamanız gerekir. Kulağa basit geliyor, ama derslerde en sık karşılaştığım "neden çalışmıyor?" sorularından biri de tam olarak bu iki adımda yapılan küçük hatalardan çıkar. Bu yazıda adımları, çözünürlük desteğini, SVG ve ağ resimlerini ve bu hataların nasıl ayıklanacağını ele alıyoruz.
Adım 1: Resim Klasörü Oluşturma
Flutter projenizin kök dizininde (lib klasörü ile aynı seviyede) bir resim klasörü oluşturun. Proje yapısını ilk kez görüyorsanız Flutter'a başlangıç rehberinde klasörlerin ne işe yaradığını anlatmıştım:
my_flutter_app/
├── lib/
├── assets/
│ └── images/
│ ├── logo.png
│ ├── profile.jpg
│ └── banner.png
├── pubspec.yaml
└── ...Not: Klasör ismi genellikle assets, images veya assets/images şeklinde olur. İstediğiniz ismi verebilirsiniz, ama ekip çalışmasında herkesin beklediği yerleşim assets/images/ biçimidir.
Adım 2: pubspec.yaml Yapılandırması
pubspec.yaml dosyasını açın ve flutter: bölümünün altına assets tanımlamasını ekleyin; bu bölümün yazım kurallarının tamamı Flutter'ın "Adding assets and images" rehberinde anlatılıyor:
Tek Bir Resim Ekleme
flutter:
uses-material-design: true
assets:
- assets/images/logo.pngTüm Klasörü Ekleme
flutter:
uses-material-design: true
assets:
- assets/images/Klasör yolu sonunda / işareti olursa, o klasördeki tüm dosyalar asset olarak eklenir. Alt klasörler bu tanıma dahil değildir; tek istisna, aşağıda göreceğimiz 2.0x, 3.0x gibi çözünürlük klasörleridir.
Alt Klasörlerle Birlikte
flutter:
assets:
- assets/images/
- assets/images/icons/
- assets/images/backgrounds/Örnek pubspec.yaml
name: my_app
description: My Flutter application.
environment:
sdk: ^3.9.0
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/icons/environment altındaki sdk satırını elle yazmanız gerekmez; flutter create bunu kurulu Dart sürümüne göre doldurur. Buradaki ^3.9.0, Flutter 3.35 ile gelen Dart sürümüne karşılık gelir.
Adım 3: Resimleri Kullanma
Image.asset Widget
Image.asset, Image widget'ının API dokümanında listelenen kuruculardan biridir ve diğerleri gibi sıradan bir widget'tır; widget ağacında Row, Column ya da Container içine koyabilirsiniz:
Image.asset('assets/images/logo.png')Boyutlandırma
Image.asset(
'assets/images/logo.png',
width: 200,
height: 200,
)BoxFit ile Sığdırma
Image.asset(
'assets/images/banner.png',
width: double.infinity,
height: 200,
fit: BoxFit.cover, // Alanı kapla
)BoxFit değerleri:
cover: Alanı tamamen kaplar, taşan kısmı kırparcontain: Resmin tamamı görünür, boşluk kalabilirfill: Alanı doldurur, en-boy oranı bozulabilirfitWidth: Genişliğe göre sığdırırfitHeight: Yüksekliğe göre sığdırırnone: Orijinal boyutta gösterirscaleDown:containgibi davranır ama resmi hiçbir zaman büyütmez
Pratik Kullanım Örnekleri
Örnek 1: Logo Gösterme
class LogoWidget extends StatelessWidget {
const LogoWidget({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Image.asset(
'assets/images/logo.png',
width: 150,
height: 150,
),
);
}
}Örnek 2: Profil Resmi
const CircleAvatar(
radius: 50,
backgroundImage: AssetImage('assets/images/profile.jpg'),
)CircleAvatar bir widget değil, bir ImageProvider bekler; bu yüzden burada Image.asset yerine AssetImage kullanılır.
Örnek 3: Banner Resmi
SizedBox(
width: double.infinity,
height: 200,
child: Image.asset(
'assets/images/banner.png',
fit: BoxFit.cover,
),
)Yalnızca boyut vermek için Container yerine SizedBox kullanmak hem daha hafif hem de niyeti daha açık bir yazımdır.
Örnek 4: Icon Resmi
Row(
children: [
Image.asset(
'assets/images/icons/star.png',
width: 24,
height: 24,
),
const SizedBox(width: 8),
const Text('Favorilerim'),
],
)İkon ile metin arasındaki boşluğu veren SizedBox bu tür küçük satırlarda en pratik araç.
Örnek 5: Arka Plan Resmi
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/background.jpg'),
fit: BoxFit.cover,
),
),
child: const Center(
child: Text(
'Hoş Geldiniz',
style: TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
),
)Resmin üzerine birden fazla öğeyi serbestçe yerleştirmeniz gerekiyorsa Stack ve Positioned daha esnek bir yoldur.
Çoklu Ekran Desteği için Resimler
Farklı ekran yoğunluklarına göre farklı çözünürlükte resimler kullanabilirsiniz:
Klasör Yapısı
assets/
└── images/
├── logo.png (1x, ana dosya)
├── 1.5x/
│ └── logo.png (1.5x)
├── 2.0x/
│ └── logo.png (2x)
├── 3.0x/
│ └── logo.png (3x)
└── 4.0x/
└── logo.png (4x)Her klasördeki dosya aynı adı taşır; yalnızca piksel boyutu farklıdır. Örneğin logo.png 100x100 piksel ise 2.0x/logo.png 200x200, 3.0x/logo.png 300x300 piksel olmalıdır.
pubspec.yaml
flutter:
assets:
- assets/images/logo.pngNot: Flutter 1.5x, 2.0x, 3.0x, 4.0x klasörlerindeki varyantları ana dosyayla birlikte otomatik olarak pakete ekler, bunları ayrıca belirtmeye gerek yok.
Kullanımı
Image.asset('assets/images/logo.png')Flutter, cihazın devicePixelRatio değerine en yakın varyantı otomatik olarak seçer. Kodda her zaman ana dosyanın yolunu yazarsınız. Aynı resmi iki sayfa arasında büyüyerek uçurmak isterseniz Image.asset'i bir Hero içine almanız yeter; ayrıntıları Hero animasyonları yazısında bulabilirsiniz.
Resim İsimlendirme Önerileri
Çözünürlüğü dosya adına yazmayın; logo_low.png, logo_high.png gibi isimler Flutter'ın otomatik seçimini devre dışı bırakır ve hangi dosyanın ne zaman kullanılacağına kodda sizin karar vermenizi gerektirir. Çözünürlük için yukarıdaki 2.0x, 3.0x klasörlerini kullanın.
Dosya adlarında şu kurallar işinizi kolaylaştırır:
onboarding_step1.png // küçük harf, kelimeler alt çizgiyle
icon_cart_24.png // farklı boyutta kullanılan ikonlarda boyut adın sonunda
bg_login.jpg // türüne göre ön ek (bg_, icon_, img_)Boşluk, Türkçe karakter ve büyük harf kullanmayın. Bazı dosya sistemleri büyük/küçük harfe duyarlıdır; bilgisayarınızda çalışan Logo.PNG bir başka ortamda bulunamayabilir.
Yolları Tek Yerde Toplayın
Resim yolları kodun farklı yerlerinde metin olarak tekrar ettiğinde bir yazım hatası ancak çalışma zamanında fark edilir. Yolları sabit olarak tek bir yerde tutmak bu riski azaltır:
abstract final class AppImages {
static const logo = 'assets/images/logo.png';
static const profile = 'assets/images/profile.jpg';
static const banner = 'assets/images/banner.png';
}
// Kullanım
Image.asset(AppImages.logo)abstract final class, Dart 3 ile gelen bir yazımdır: sınıftan nesne oluşturulamaz ve dışarıdan genişletilemez, yani yalnızca sabitleri gruplamak için kullanıldığı açıkça belli olur.
Yükleme ve Hata Durumları
Yumuşak Görünme (frameBuilder)
Image.asset(
'assets/images/logo.png',
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) {
return child;
}
return AnimatedOpacity(
opacity: frame == null ? 0 : 1,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
child: child,
);
},
)frame ilk kare çözülene kadar null gelir; bu örnek resmi o ana kadar görünmez tutup sonra yumuşakça belirginleştirir.
Hata Durumu
Image.asset(
'assets/images/logo.png',
errorBuilder: (context, error, stackTrace) {
return Container(
color: Colors.grey.shade300,
child: const Center(
child: Icon(Icons.error, color: Colors.red),
),
);
},
)errorBuilder, dosya bulunamadığında ya da çözülemediğinde kırmızı hata ekranı yerine sizin belirlediğiniz widget'ı gösterir. Asset'ler için bu çoğu zaman bir yapılandırma hatasının işaretidir; hatayı gizlemek yerine önce aşağıdaki "Sık Yapılan Hatalar" bölümünü kontrol edin.
Image.network ve Image.asset
Image.asset (Yerel Resim)
Image.asset('assets/images/logo.png')- Uygulama paketine dahildir
- İnternet gerektirmez
- Hızlı yüklenir
- Uygulama boyutunu artırır
Image.network (İnternetten Resim)
Image.network('https://example.com/image.png')- Çalışma zamanında internetten indirilir
- İnternet bağlantısı gerektirir
- Bağlantı hızına göre gecikebilir
- Uygulama boyutunu artırmaz
- Flutter indirilen resimleri yalnızca bellekte (
ImageCache) tutar; uygulama kapanınca yeniden indirilir. Diske önbellekleme için aşağıdakicached_network_imagepaketi kullanılır.
FadeInImage ile Yumuşak Yükleme
Ağdan gelen resim yüklenirken yerel bir yer tutucu göstermek için:
FadeInImage.assetNetwork(
placeholder: 'assets/images/placeholder.png',
image: 'https://example.com/image.png',
fit: BoxFit.cover,
)Aynı sonuç ImageProvider'larla da elde edilebilir:
FadeInImage(
placeholder: const AssetImage('assets/images/placeholder.png'),
image: const NetworkImage('https://example.com/image.png'),
fit: BoxFit.cover,
)Yer tutucu bir asset olduğu için anında görünür; ağ resmi gelince yumuşak bir geçişle yerini alır.
SVG Resimler
Flutter'ın Image widget'ı SVG çizemez; bunun için flutter_svg paketi gerekir. Paketi terminalden ekleyin:
flutter pub add flutter_svgBu komut paketin güncel sürümünü pubspec.yaml içindeki dependencies bölümüne kendisi yazar.
Kullanımı
import 'package:flutter_svg/flutter_svg.dart';
SvgPicture.asset(
'assets/images/logo.svg',
width: 100,
height: 100,
semanticsLabel: 'Uygulama logosu',
)SVG dosyasının da pubspec.yaml içinde asset olarak tanımlı olması gerekir. Rengini değiştirmek için colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn) kullanılır.
Cached Network Image
Ağ resimlerini diske önbelleklemek için cached_network_image paketi:
flutter pub add cached_network_imageKullanımı
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://example.com/image.png',
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
)Resim bir kez indirildikten sonra cihazda saklanır; sonraki açılışlarda ağa gitmeden gösterilir.
Sık Yapılan Hatalar
1. pubspec.yaml Girintisi
# ❌ YANLIŞ
flutter:
uses-material-design: true
assets:
- assets/images/
# ✅ DOĞRU
flutter:
uses-material-design: true
assets:
- assets/images/YAML'da girinti anlam taşır. assets: satırı flutter: altında iki boşluk içeride olmalıdır; sekme (tab) karakteri kullanmayın.
2. Yol Hatası
// ❌ YANLIŞ
Image.asset('images/logo.png') // 'assets/' eksik
// ✅ DOĞRU
Image.asset('assets/images/logo.png')Koddaki yol, pubspec.yaml içindeki yolla birebir aynı başlamalıdır.
3. Dosya Adı Büyük/Küçük Harf
// Dosyanın adı logo.PNG ise:
Image.asset('assets/images/logo.png') // Bazı ortamlarda bulunamazDosya sisteminiz büyük/küçük harfe duyarlı olabilir; dosya adıyla koddaki yolu harfi harfine eşleştirin.
4. Alt Klasörü Tanımlamayı Unutmak
assets/images/ tanımı assets/images/icons/ içindeki dosyaları kapsamaz. Her alt klasörü ayrı bir satır olarak ekleyin.
5. Hot Reload Sorunu
pubspec.yaml değişiklikleri için:
- Hot reload yeterli değil
- Hot restart yapın (🔄 butonu)
- Hâlâ "Unable to load asset" görüyorsanız uygulamayı tamamen durdurup yeniden başlatın
Özet
Flutter'da resim eklemek:
- Klasör oluştur:
assets/images/ - Resimleri ekle: PNG, JPG, WebP; SVG için ayrıca
flutter_svg - pubspec.yaml'a tanımla:
flutter: assets: - assets/images/ - Hot restart yap
- Kullan:
Image.asset('assets/images/logo.png')
Öneriler:
- Çoklu çözünürlük için
2.0x,3.0xklasörleri oluşturun - Anlamlı, küçük harfli dosya isimleri kullanın
- Resim yollarını tek bir sabitler sınıfında toplayın
- SVG resimler için
flutter_svgkullanın - Ağ resimlerini diske önbelleklemek için
cached_network_imagekullanın
Performans İpuçları:
- Resimleri ekranda gösterilecekleri boyuttan çok daha büyük eklemeyin
- WebP formatı çoğu zaman PNG ve JPG'den daha küçük dosya boyutu sağlar
- Büyük bir resmi küçük bir alanda gösteriyorsanız
cacheWidthveyacacheHeightvererek bellekte küçük boyutta çözülmesini sağlayın:Image.asset('assets/images/banner.png', cacheWidth: 600) - Uzun resim listelerinde
ListView.builderkullanın; yalnızca ekranda görünen öğeler oluşturulur - Kullanılmayan resimleri projeden silin
Resimler, Flutter uygulamalarının görsel kimliğinin önemli bir parçasıdır. Doğru boyutta, doğru yerde ve doğru biçimde kullanıldıklarında uygulamanız hem hızlı hem de özenli görünür. Uygulamanın kendi ikonu ise asset değil, platform kaynağıdır; onu uygulama ikonu oluşturma yazısında ayrı ele aldım.
Sık Sorulan Sorular
pubspec.yaml'a ekledim ama "Unable to load asset" hatası alıyorum, neden?
Üç şüpheli var: assets: satırının flutter: altında iki boşluk girintili olması, koddaki yolun assets/images/logo.png gibi tam yol olması ve pubspec değişikliğinden sonra hot restart yapılmış olması. Alt klasörlerin de ayrı ayrı listelenmesi gerektiğini unutmayın.
Resimleri assets yerine lib klasörüne koyabilir miyim?
Teknik olarak evet, yine de pubspec.yaml'da tanımlamanız gerekir. Ama lib kod içindir; resimleri projenin kökündeki assets/ altında tutmak hem düzeni korur hem de ekip arkadaşlarınızın beklediği yerleşimdir.
Resimler uygulama boyutunu çok büyütüyor, ne yapmalıyım?
PNG yerine WebP kullanın, görselleri gerçekten gösterilecekleri boyuta indirin ve kullanılmayan dosyaları silin. Nadiren görüntülenen büyük görselleri uygulamaya gömmek yerine cached_network_image ile ağdan yüklemek de boyutu ciddi ölçüde düşürür.
İlgili Yazılar
Flutter: Theme ve ThemeData ile Açık ve Koyu Tema
Flutter'da ThemeData ile tema kurmak: ColorScheme.fromSeed, açık ve koyu tema, ThemeMode, Theme.of ile okuma, TextTheme, bileşen temaları ve ThemeExtension.
Flutter: TextField ve TextEditingController Kullanımı
Flutter TextField rehberi: TextEditingController ve dispose, InputDecoration, klavye tipleri, inputFormatters, şifre alanı, FocusNode ve onChanged farkı.
Flutter: Stack ve Positioned ile Üst Üste Yerleşim
Flutter Stack ve Positioned rehberi: Stack'in boyutu, fit, alignment, clipBehavior, Positioned.fill, PositionedDirectional, rozet ve katman tarifleri, hatalar.