Özel View'da Nasıl Çizim Yapılır: Canvas, Paint ve Hata Ayıklama

Kerem Aydın·9 Temmuz 2026·⏱3 dk

Özel View'da çizim yapmak için onDraw(Canvas) metodunu geçersiz kılın, Paint nesnesini kurucu/init() metodunda önceden başlatın, Canvas.draw* (circle, line, path, text, bitmap) metodlarını kullanın ve animasyonlar için postInvalidateOnAnimation() veya kısmi yeniden çizim için invalidate(Rect) çağırın — böylece doğru, hızlı ve hata ayıklanabilir bir çizim elde edersiniz.

Canvas ve Paint Temelleri

Canvas — tuval; Paint — ayarlarla donatılmış fırça (renk, genişlik, stil, shader'lar, yumuşatma).

  • View oluşturun ve kaynakları bir kez başlatın:
public class MyView extends View {
  private Paint paint;
  public MyView(Context ctx) {
    super(ctx);
    init();
  }
  private void init() {
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(Color.RED);
    paint.setStyle(Paint.Style.FILL);
    paint.setStrokeWidth(4f);
  }
  @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawCircle(100, 100, 50, paint);
  }
}
  • Sık kullanılan Canvas metodları: drawLine, drawRect, drawCircle, drawPath, drawText, drawBitmap.
  • Karmaşık şekiller için Path:
Path p = new Path();
p.moveTo(50,50);
p.lineTo(150,50);
p.lineTo(100,150);
p.close();
canvas.drawPath(p, paint);
  • Gradyanlar ve efektler: paint.setShader(...) üzerinden Shader (LinearGradient, RadialGradient). Şekilleri doldurmak için Paint.Style.FILL, kenarlık çizmek için STROKE kullanın.

Paint, Path ve Bitmap nesnelerini init/kurucu metodda başlatın. onDraw içinde nesne oluşturmak performansı ciddi şekilde düşürür.

Etkileşim ve Animasyon

  • Dokunma işleme: onTouchEvent metodunu geçersiz kılın, koordinatları veya Path'i kaydedin ve yeniden çizim için invalidate() çağırın.
@Override public boolean onTouchEvent(MotionEvent e) {
  if (e.getAction() == MotionEvent.ACTION_DOWN || e.getAction() == MotionEvent.ACTION_MOVE) {
    path.lineTo(e.getX(), e.getY());
    invalidate(); // veya invalidate(dirtyRect)
  }
  return true;
}
  • Animasyon: 60 FPS için postInvalidateOnAnimation() veya Choreographer kullanın; senkronizasyon olmadan sık sık invalidate çağıran zamanlayıcılardan kaçının.
// basit bir animasyon adımı örneği
void step() {
  updateState();
  postInvalidateOnAnimation();
}
  • Kısmi yeniden çizim için alanı belirtin: invalidate(left, top, right, bottom) veya invalidate(Rect), bu CPU/GPU tasarrufu sağlar.
  • Donanımsal/yazılımsal render: Bazı efektlerle ilgili sorunlarda setLayerType(LAYER_TYPE_SOFTWARE, paint) deneyin veya tam tersini yapın — donanımsal hızlandırma genellikle daha hızlıdır.

Çizim Hata Ayıklama ve Optimizasyonu

  • onDraw çağrılarını sıklığını anlamak için loglayın:
Log.d("DRAW", "onDraw at " + System.currentTimeMillis());
  • Profile GPU Rendering (Geliştirici Seçeneklerinde etkinleştirilir) darboğazların nerede olduğunu gösterir.
  • Android Studio'daki Layout Inspector/Hierarchy Viewer, karmaşık View hiyerarşisini ve FPS'i görmeye yardımcı olur.
  • Optimizasyon ipuçları:
    • onDraw içinde nesne oluşturmayı en aza indirin.
    • Karmaşık render'ları Bitmap'e önbelleğe alın ve zaten hazır olan bitmap'i çizin.
    • Alfa kanalı ve blend modlarını tutumlu kullanın.
    • Sadece değişen alanları güncelleyin.
    • Sık güncellenen animasyonlar için gerekirse SurfaceView veya RenderThread kullanın.

Throttling olmadan tight loop içinde invalidate() çağırmayın — bu pilinizi hızla tüketir ve cihazın kapasitesini aşabilir.

Sık Yapılan Hatalar

  • Paint'in onDraw içinde başlatılması → FPS düşüşü.
  • invalidate() ve requestLayout() karıştırılması — requestLayout() ölçümleri yeniden hesaplar ve daha fazla iş yükü yaratır.
  • Yanlış koordinatlar: padding, canvas.translate() ve getWidth()/getHeight() boyutlarını dikkate almayı unutmayın.
  • LayerType'nin tekrar tekrar değiştirilmesi veya arka planda sık değişiklik yapılmasından kaynaklanan titreme — önbellekleme kullanın.

SSS

  • Karmaşık şekiller için her zaman Path kullanmak gerekir mi?
    • Evet, Path esneklik sağlar; statik karmaşık öğeler için bunları bir kez Bitmap'e çizmek daha iyidir.
  • 60 FPS'de nasıl sorunsuz animasyon yapılır?
    • postInvalidateOnAnimation() veya Choreographer kullanın, durumu delta zamanı dikkate alarak güncelleyin.
  • Hizalamalı metin nasıl çizilir?
    • paint.setTextSize(), paint.setTextAlign(Paint.Align.CENTER) ayarlayın ve baseline'ı paint.getFontMetrics() üzerinden hesaplayın.

Bu uygulamaları hayata geçirin: Kaynakları önceden başlatın, sadece gerekli alanları yeniden çizin ve yerleşik profil oluşturma araçlarını kullanın — bu, özel View'larınızda kararlı, akıcı ve öngörülebilir grafikler sağlayacaktır.