Özel Görünümler, herhangi bir mobil uygulamanın benzersiz arayüzünün temelidir. Mobil uygulamalardaki Özel Görünümler, standart bileşenlerde bulunmayan kendi grafiklerinizi, animasyonlarınızı ve öğelerinizi oluşturmanıza olanak tanır. Apple Developer, 2025'e göre, drawRect iOS mobil geliştirmede özel çizimin ana yöntemi olmaya devam ediyor. Android'de, Canvas ile onDraw aynı rolü oynarken, Flutter'da — CustomPainter bu rolü üstlenir.
Ana Noktalar
Özel Görünümler, benzersiz grafikler oluşturmak için standart çizim ve ölçüm yöntemlerini geçersiz kılan kullanıcı tanımlı arayüz bileşenleridir. Grafikler, animasyonlar, diyagramlar, özel sohbet öğeleri ve AR maskeleri — bunlar mobil uygulamalarda Özel Görünümlerin tipik kullanım senaryolarıdır. Standart UI bileşenleri (Button, TextView, Label) görevlerin %80'ini kapsar, ancak kalan %20'lik kısım mobil geliştirmede çizim üzerinde tam kontrol gerektirir. Mobil geliştirmede çizim, junior geliştiriciyi senior'dan ayıran bir beceridir.
Mobil uygulamalardaki Özel Görünümler, benzersiz 2D grafikler, karmaşık animasyonlar, çizelgeler ve veri görselleştirme için gereklidir. Standart UIKit gerekli öğeyi sağlamıyorsa — özel bir Görünüm oluşturulur. Mobil uygulamalarda, Özel Görünümler ilerleme çubukları, özel düğmeler, degrade dolgular, animasyonlu simgeler ve parmakla çizim tuvalleri için kullanılır. Aşırı kullanmamak önemlidir — basit stiller için, standart bileşenleri Görünüm API'si aracılığıyla yapılandırmak yeterlidir.
iOS'ta, Özel Görünümler UIView'den miras alınarak ve drawRect yöntemi geçersiz kılınarak oluşturulur. drawRect, ilk render'da ve her setNeedsDisplay() çağrısından sonra çağrılır. drawRect'in içinde, geliştirici UIGraphicsGetCurrentContext() aracılığıyla bir CGContext alır — çizgiler, şekiller, degradeler ve metin için bir tuval. Core Graphics (Quartz 2D), her piksel üzerinde tam kontrol sağlayan düşük seviyeli CPU tabanlı bir render motorudur. UIBezierPath, kısa sözdizimiyle yollar oluşturmak için kullanışlı bir sarmalayıcıdır.
class CircleView: UIView {
private var fillColor: UIColor = .systemBlue
override func drawRect(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.setFillColor(fillColor.cgColor)
ctx.addEllipse(in: bounds.insetBy(dx: 4, dy: 4))
ctx.drawPath(using: .fill)
}
func updateColor(_ newColor: UIColor) {
fillColor = newColor
setNeedsDisplay()
}
}
Core Graphics, tüm çizim işlemleri için CGContext — bir tuval sağlar. CGGradient, CGColorSpace (sRGB, Display P3) desteğiyle doğrusal ve radyal degradeler oluşturur. Dönüşümler CGAffineTransform aracılığıyla gerçekleştirilir — döndürme, ölçekleme ve kaydırma için 3x3 matris. CGContextTranslateCTM, CGContextRotateCTM ve CGContextScaleCTM koordinat sistemini değiştirir. Core Graphics CPU'da çalışır, bu nedenle karmaşık grafikler işlemciyi yükleyebilir — GPU hızlandırması için Metal kullanın.
UIBezierPath, CGPath üzerinde nesne yönelimli bir sarmalayıcıdır. addArc(withCenter:radius:startAngle:endAngle:clockwise:) yöntemi yaylar ve daireler oluşturur, addCurve Bézier eğrileri oluşturur. Yollar, addClip aracılığıyla birleşim, kesişim ve çıkarma işlemlerini destekler. UIBezierPath, özel maskeler (maskView), kırpma yolları ve karmaşık şekiller — yıldızlar, kalpler, özel simgeler için kullanışlıdır.
Android'de, özel bir Görünüm, onDraw(Canvas) geçersiz kılınarak View'i genişletir. Canvas, mobil geliştirmedeki tüm çizim yöntemlerini içerir: drawCircle, drawRect, drawLine, drawText, drawBitmap, drawPath ve drawRoundRect. Paint, parametreleri yapılandırır — renk, çizgi kalınlığı, stil (FILL, STROKE, FILL_AND_STROKE), kenar yumuşatma (isAntiAlias) ve metin boyutu. onDraw, her invalidate()'de çağrılır ve ağır işlemler içermemelidir — tüm hesaplamalar önbelleğe alınır.
class CustomCircleView(context: Context, attrs: AttributeSet?)
: View(context, attrs) {
private val paint = Paint().apply {
style = Paint.Style.FILL
color = Color.BLUE
isAntiAlias = true
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = minOf(cx, cy) - 4f
canvas.drawCircle(cx, cy, radius, paint)
}
}
Android'de Path, UIBezierPath'in eşdeğeridir: addCircle, addRect, addOval, lineTo, cubicTo ve quadTo. PathMeasure, yol uzunluğunu ve herhangi bir noktadaki koordinatları hesaplar — bir nesnenin bir yol boyunca hareketini canlandırmak için kullanışlıdır. Animasyonlar için, geri çağrımda invalidate() ile ValueAnimator kullanılır. Animator, rengi, yarıçapı, konumu değiştirebilir — çizimi etkileyen herhangi bir özellik. Android'deki Özel Görünümler ayrıca XML aracılığıyla animasyon için StateListDrawable ve animated-vector'u da destekler.
Android'de degradeler Shader aracılığıyla ayarlanır — LinearGradient, RadialGradient ve SweepGradient. Shader, paint.setShader(shader) aracılığıyla Paint'e atanır. LinearGradient, iki nokta arasında isteğe bağlı renk konumlarıyla doğrusal bir degrade oluşturur. RadialGradient — merkezden kenarlara radyal. SweepGradient — bir merkez noktası etrafında konik. Shader.TileMode (CLAMP, REPEAT, MIRROR), alan sınırlarının ötesindeki davranışı tanımlar.
Flutter, CustomPainter kullanır — paint(Canvas canvas, Size size) ve shouldRepaint yöntemlerine sahip bir sınıf. Flutter'daki Canvas, Android'dekiyle aynı yöntemleri sağlar: drawCircle, drawRect, drawLine, drawPath, drawParagraph ve drawImage. Flutter'daki Paint, rengi, kalınlığı, stili ve kenar yumuşatmayı yapılandırır. Flutter, drawRect veya onDraw kullanmaz — tüm çizim, CustomPaint widget'ına yerleştirilmiş CustomPainter aracılığıyla yapılır.
class CirclePainter extends CustomPainter {
final Color color;
CirclePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..style = PaintingStyle.fill
..isAntiAlias = true;
final radius = size.shortestSide / 2 - 4;
canvas.drawCircle(size.center(Offset.zero), radius, paint);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) =>
oldDelegate.color != color;
}
shouldRepaint, CustomPainter'ın yeniden çizilmesi gerekip gerekmediğini belirler. Yalnızca işlemeyi etkileyen veriler değiştiğinde true döndürün — renk, boyut, grafik verileri. RepaintBoundary, yeniden çizmeyi ayrı bir katmanda yalıtır — nadiren değişen widget'lar için kullanın. Flutter'da setNeedsDisplay veya invalidate yoktur — yeniden çizme, setState veya değişiklikleri dinleyen ValueNotifier aracılığıyla tetiklenir.
Flutter, LinearGradient, RadialGradient ve SweepGradient'i destekler — Android'dekiyle aynı türler. Gradient, createShader(Rect bounds) aracılığıyla Paint için Shader oluşturur. Dönüşümler canvas.rotate, canvas.scale, canvas.translate ve canvas.skew aracılığıyla gerçekleştirilir. Flutter, Transform widget'ı için 4x4 dönüşüm matrisi (Matrix4) kullanır. Flutter'da çizim animasyonları, CustomPainter'ı yeniden çizmek için setState ile birlikte AnimationController kullanılarak yapılır.
Özel Görünümlerin doğru ölçümü, öngörülebilir arayüz davranışının temelidir. iOS'ta, Görünümün boyutu sizeThatFits ve intrinsicContentSize aracılığıyla belirlenir. sizeThatFits, verilen kısıtlamalar için en uygun boyutu döndürür. intrinsicContentSize — harici kısıtlamalar olmadan içeriğin doğal boyutu. Android'de ölçüm, MeasureSpec parametreleriyle (UNSPECIFIED, EXACTLY, AT_MOST) onMeasure'da uygulanır. Flutter'da boyut, paint(Canvas, Size)'e iletilir ve computeDryLayout veya LayoutBuilder aracılığıyla hesaplanabilir.
intrinsicContentSize bir CGSize döndürür — içeriğine dayalı olarak Görünümün doğal boyutu. setContentHuggingPriority ve setContentCompressionResistancePriority, germe ve sıkıştırma sırasındaki davranışı kontrol eder. sizeThatFits, Auto Layout'da boyutu hesaplamak için sistem tarafından çağrılır. Özel Görünümler için, bileşeninizin doğal bir boyutu varsa intrinsicContentSize'ı geçersiz kılın — örneğin, bir daire her zaman 100x100 olmalıdır.
onMeasure, widthMeasureSpec ve heightMeasureSpec'i kabul eder. MeasureSpec, mod ve boyut içerir: UNSPECIFIED (kısıtlama yok, Görünüm kendi boyutunu seçer), EXACTLY (üst öğeden tam boyut), AT_MOST (maksimum boyut). setMeasuredDimension(width, height) ölçüm sonucunu kaydeder. Veriler değiştiğinde, yeniden ölçüm için requestLayout() çağrısı yapın. İç içe ViewGroup'lar, alt öğeleri düzenlemek için onLayout'u geçersiz kılmayı gerektirir.
| Platform | Ölçüm yöntemi | Değişiklikte çağrı | Dönüş |
|---|---|---|---|
| iOS | sizeThatFits / intrinsicContentSize | setNeedsLayout / invalidateIntrinsicContentSize | CGSize |
| Android | onMeasure / setMeasuredDimension | requestLayout / invalidate | void (boyutu kaydeder) |
| Flutter | computeDryLayout | setState / LayoutBuilder | Size |
computeDryLayout, tam bir düzen döngüsü olmadan boyutu hesaplamak için bir RenderObject yöntemidir. LayoutBuilder.getSize — build yönteminde kullanılabilir alanı almak için bir alternatiftir. Flutter'da tuval boyutu, paint'e Size olarak iletilir ve ayrı bir ölçüm gerektirmez — CustomPainter, iletilen sınırlar içinde çizer. Ancak, özel RenderObject'ler için performLayout ve computeDryLayout'u geçersiz kılmanız gerekir.
Sıkça Sorulan Sorular
drawRect, Core Graphics aracılığıyla özel çizim için bir UIView yöntemidir. Görünümün ilk render'ında ve her setNeedsDisplay() çağrısından sonra çağrılır. Çizgiler, şekiller ve metin için drawRect içinde CGContext kullanın.
View'i genişleten bir sınıf oluşturun, onDraw(Canvas canvas)'ı geçersiz kılın ve Canvas API'sini kullanın: drawCircle, drawRect, drawPath. Paint, rengi, kalınlığı ve stili yapılandırır. Güncellemek için invalidate() çağrısı yapın.
CustomPainter, Canvas üzerinde özel çizim için bir Flutter sınıfıdır. paint(Canvas, Size) ve shouldRepaint yöntemlerini uygulayın. CustomPaint widget'ı aracılığıyla yerleştirilir. Flutter'da drawRect yoktur — tüm çizim CustomPainter aracılığıyla yapılır.
iOS'ta sizeThatFits ve intrinsicContentSize kullanın. Android'de — MeasureSpec ile onMeasure. Flutter'da boyut, paint(Canvas, Size)'e iletilir veya computeDryLayout aracılığıyla hesaplanır. Her platform kendi ölçüm yöntemini kullanır.
Özel Görünümler, standart UIKit veya View ile uygulanamayan benzersiz grafikler, animasyonlar, çizelgeler ve öğeler için gereklidir. Basit stiller için, standart bileşenleri yapılandırmak yeterlidir — mimariyi gereksiz yere karmaşıklaştırmayın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.