Tampilan Kustom adalah fondasi antarmuka unik dari setiap aplikasi seluler. Tampilan Kustom di aplikasi seluler memungkinkan Anda membuat grafis, animasi, dan elemen sendiri yang tidak tersedia di komponen standar. Menurut Apple Developer, 2025, drawRect tetap menjadi metode utama menggambar kustom dalam pengembangan seluler iOS. Di Android, onDraw dengan Canvas memainkan peran yang sama, dan di Flutter — CustomPainter.
Poin Utama
Tampilan Kustom adalah komponen antarmuka yang ditentukan pengguna yang menimpa metode menggambar dan pengukuran standar untuk membuat grafis unik. Grafik, animasi, diagram, elemen obrolan kustom, dan topeng AR — ini adalah skenario penggunaan umum Tampilan Kustom di aplikasi seluler. Komponen UI standar (Button, TextView, Label) mencakup 80% tugas, tetapi 20% sisanya memerlukan kontrol penuh atas menggambar dalam pengembangan seluler. Menggambar dalam pengembangan seluler adalah keterampilan yang membedakan pengembang junior dari senior.
Tampilan Kustom di aplikasi seluler diperlukan untuk grafis 2D unik, animasi kompleks, bagan, dan visualisasi data. Jika UIKit standar tidak menyediakan elemen yang diperlukan — Tampilan Kustom dibuat. Di aplikasi seluler, Tampilan Kustom digunakan untuk bilah kemajuan, tombol kustom, isian gradien, ikon animasi, dan kanvas menggambar dengan jari. Penting untuk tidak berlebihan — untuk gaya sederhana, cukup konfigurasi komponen standar melalui API Penampilan.
Di iOS, Tampilan Kustom dibuat dengan mewarisi UIView dan menimpa metode drawRect. drawRect dipanggil pada render pertama dan setelah setiap panggilan setNeedsDisplay(). Di dalam drawRect, pengembang mendapatkan CGContext melalui UIGraphicsGetCurrentContext() — kanvas untuk garis, bentuk, gradien, dan teks. Core Graphics (Quartz 2D) adalah mesin rendering tingkat rendah berbasis CPU yang memberikan kontrol penuh atas setiap piksel. UIBezierPath adalah pembungkus yang nyaman untuk membuat jalur dengan sintaksis ringkas.
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 menyediakan CGContext — kanvas untuk semua operasi menggambar. CGGradient membuat gradien linier dan radial dengan dukungan CGColorSpace (sRGB, Display P3). Transformasi dilakukan melalui CGAffineTransform — matriks 3x3 untuk rotasi, penskalaan, dan translasi. CGContextTranslateCTM, CGContextRotateCTM, dan CGContextScaleCTM memodifikasi sistem koordinat. Core Graphics berjalan di CPU, sehingga grafis kompleks dapat membebani prosesor — gunakan Metal untuk akselerasi GPU.
UIBezierPath adalah pembungkus berorientasi objek di atas CGPath. Metode addArc(withCenter:radius:startAngle:endAngle:clockwise:) membuat busur dan lingkaran, addCurve membuat kurva Bézier. Jalur mendukung operasi gabungan, irisan, dan pengurangan melalui addClip. UIBezierPath berguna untuk topeng kustom (maskView), jalur kliping, dan bentuk kompleks — bintang, hati, ikon kustom.
Di Android, Tampilan Kustom memperluas View dengan onDraw(Canvas) ditimpa. Canvas berisi semua metode menggambar dalam pengembangan seluler: drawCircle, drawRect, drawLine, drawText, drawBitmap, drawPath, dan drawRoundRect. Paint mengonfigurasi parameter — warna, ketebalan garis, gaya (FILL, STROKE, FILL_AND_STROKE), anti-aliasing (isAntiAlias), dan ukuran teks. onDraw dipanggil setiap kali invalidate() dan tidak boleh berisi operasi berat — semua perhitungan di-cache.
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)
}
}
Path di Android setara dengan UIBezierPath: addCircle, addRect, addOval, lineTo, cubicTo, dan quadTo. PathMeasure menghitung panjang jalur dan koordinat di titik mana pun — berguna untuk menganimasikan pergerakan objek di sepanjang jalur. Untuk animasi, gunakan ValueAnimator dengan invalidate() di callback. Animator dapat mengubah warna, radius, posisi — properti apa pun yang memengaruhi menggambar. Tampilan Kustom di Android juga mendukung StateListDrawable dan animated-vector untuk animasi melalui XML.
Gradien di Android diatur melalui Shader — LinearGradient, RadialGradient, dan SweepGradient. Shader ditugaskan ke Paint melalui paint.setShader(shader). LinearGradient menghasilkan gradien linier antara dua titik dengan posisi warna opsional. RadialGradient — radial dari pusat ke tepi. SweepGradient — kerucut di sekitar titik pusat. Shader.TileMode (CLAMP, REPEAT, MIRROR) menentukan perilaku di luar batas area.
Flutter menggunakan CustomPainter — kelas dengan metode paint(Canvas canvas, Size size) dan shouldRepaint. Canvas di Flutter menyediakan metode yang sama seperti di Android: drawCircle, drawRect, drawLine, drawPath, drawParagraph, dan drawImage. Paint di Flutter mengonfigurasi warna, ketebalan, gaya, dan anti-aliasing. Flutter tidak menggunakan drawRect atau onDraw — semua menggambar melalui CustomPainter, yang tertanam di widget CustomPaint.
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 menentukan apakah CustomPainter perlu digambar ulang. Kembalikan true hanya ketika data yang memengaruhi rendering berubah — warna, ukuran, data bagan. RepaintBoundary mengisolasi penggambaran ulang ke lapisan terpisah — gunakan untuk widget yang jarang berubah. Flutter tidak memiliki setNeedsDisplay atau invalidate — penggambaran ulang dipicu melalui setState atau ValueNotifier dengan mendengarkan perubahan.
Flutter mendukung LinearGradient, RadialGradient, dan SweepGradient — jenis yang sama seperti di Android. Gradient membuat Shader untuk Paint melalui createShader(Rect bounds). Transformasi dilakukan melalui canvas.rotate, canvas.scale, canvas.translate, dan canvas.skew. Flutter menggunakan matriks transformasi 4x4 (Matrix4) untuk widget Transform. Animasi menggambar di Flutter dibuat dengan AnimationController dikombinasikan dengan setState untuk menggambar ulang CustomPainter.
Pengukuran yang benar dari Tampilan Kustom adalah fondasi perilaku antarmuka yang dapat diprediksi. Di iOS, ukuran Tampilan ditentukan melalui sizeThatFits dan intrinsicContentSize. sizeThatFits mengembalikan ukuran optimal untuk kendala yang diberikan. intrinsicContentSize — ukuran alami konten tanpa kendala eksternal. Di Android, pengukuran diimplementasikan di onMeasure dengan parameter MeasureSpec (UNSPECIFIED, EXACTLY, AT_MOST). Di Flutter, ukuran diteruskan ke paint(Canvas, Size) dan dapat dihitung melalui computeDryLayout atau LayoutBuilder.
intrinsicContentSize mengembalikan CGSize — ukuran alami Tampilan berdasarkan kontennya. setContentHuggingPriority dan setContentCompressionResistancePriority mengontrol perilaku selama peregangan dan kompresi. sizeThatFits dipanggil oleh sistem untuk menghitung ukuran di Auto Layout. Untuk Tampilan Kustom, timpa intrinsicContentSize jika komponen Anda memiliki ukuran alami — misalnya, lingkaran harus selalu 100x100.
onMeasure menerima widthMeasureSpec dan heightMeasureSpec. MeasureSpec berisi mode dan ukuran: UNSPECIFIED (tanpa kendala, Tampilan memilih ukurannya sendiri), EXACTLY (ukuran pasti dari induk), AT_MOST (ukuran maksimum). setMeasuredDimension(width, height) menyimpan hasil pengukuran. Saat data berubah, panggil requestLayout() untuk pengukuran ulang. ViewGroup bersarang memerlukan penimpaan onLayout untuk mengatur elemen anak.
| Platform | Metode Pengukuran | Panggilan saat perubahan | Kembalian |
|---|---|---|---|
| iOS | sizeThatFits / intrinsicContentSize | setNeedsLayout / invalidateIntrinsicContentSize | CGSize |
| Android | onMeasure / setMeasuredDimension | requestLayout / invalidate | void (menyimpan ukuran) |
| Flutter | computeDryLayout | setState / LayoutBuilder | Size |
computeDryLayout adalah metode RenderObject untuk menghitung ukuran tanpa siklus tata letak lengkap. LayoutBuilder.getSize — alternatif untuk mendapatkan ruang yang tersedia di metode build. Di Flutter, ukuran kanvas diteruskan ke paint sebagai Size dan tidak memerlukan pengukuran terpisah — CustomPainter menggambar dalam batas yang diteruskan. Namun, untuk RenderObject kustom, Anda perlu menimpa performLayout dan computeDryLayout.
Pertanyaan yang Sering Diajukan
drawRect adalah metode UIView untuk menggambar kustom melalui Core Graphics. Dipanggil pada render pertama Tampilan dan setelah setiap panggilan setNeedsDisplay(). Gunakan CGContext di dalam drawRect untuk garis, bentuk, dan teks.
Buat kelas yang memperluas View, timpa onDraw(Canvas canvas) dan gunakan Canvas API: drawCircle, drawRect, drawPath. Paint mengonfigurasi warna, ketebalan, dan gaya. Untuk memperbarui, panggil invalidate().
CustomPainter adalah kelas Flutter untuk menggambar kustom di Canvas. Implementasikan metode paint(Canvas, Size) dan shouldRepaint. Ditempatkan melalui widget CustomPaint. Flutter tidak memiliki drawRect — semua menggambar melalui CustomPainter.
Di iOS gunakan sizeThatFits dan intrinsicContentSize. Di Android — onMeasure dengan MeasureSpec. Di Flutter, ukuran diteruskan ke paint(Canvas, Size) atau dihitung melalui computeDryLayout. Setiap platform menggunakan metode pengukuran sendiri.
Tampilan Kustom diperlukan untuk grafis unik, animasi, bagan, dan elemen yang tidak dapat diimplementasikan dengan UIKit atau View standar. Untuk gaya sederhana, cukup konfigurasi komponen standar — jangan mempersulit arsitektur tanpa perlu.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.