Персонализирани изгледи и рисуване в мобилната разработка: същност, кои API и как работи

Автор: IT Sectr Публикувано: 2026-08-01 Време за четене: 11 мин

Персонализираните изгледи са основата на уникалния интерфейс на всяко мобилно приложение. Персонализираните изгледи в мобилните приложения позволяват създаването на собствена графика, анимации и елементи, недостъпни в стандартните компоненти. Според Apple Developer, 2025, drawRect остава основният метод за персонализирано рисуване в мобилната разработка на iOS. На Android същата роля изпълнява onDraw с Canvas, а във Flutter — CustomPainter.

Основни точки

  • Персонализирани изгледи — дефинирани от потребителя компоненти със собствена логика за рисуване, размер и поведение в мобилни приложения.
  • drawRect — метод на UIView на iOS за персонализирано рисуване чрез Core Graphics и CGContext.
  • onDraw — метод на View на Android за рисуване чрез Canvas и Paint с измервателна система onMeasure.
  • CustomPainter — клас на Flutter за рисуване на Canvas с методите paint и shouldRepaint.
  • Измерване — процес на определяне на размерите на Изгледа чрез sizeThatFits на iOS, onMeasure на Android и computeDryLayout във Flutter.

Какво са персонализираните изгледи и защо са необходими в мобилните приложения

Персонализираните изгледи са дефинирани от потребителя интерфейсни компоненти, които презаписват стандартните методи за рисуване и измерване, за да създадат уникална графика. Графики, анимации, диаграми, персонализирани елементи за чат и AR маски — типични сценарии за използване на персонализирани изгледи в мобилни приложения. Стандартните UI компоненти (Button, TextView, Label) покриват 80% от задачите, но останалите 20% изискват пълен контрол върху рисуването в мобилната разработка. Рисуването в мобилната разработка е умение, което отличава junior разработчика от senior.

Кога персонализираните изгледи са оправдани

Персонализираните изгледи в мобилните приложения са необходими за уникална 2D графика, сложни анимации, графики и визуализация на данни. Ако стандартният UIKit не предоставя необходимия елемент — се създава персонализиран изглед. В мобилните приложения персонализираните изгледи се използват за ленти за напредък, персонализирани бутони, градиентни запълвания, анимирани икони и платна за рисуване с пръст. Важно е да не се злоупотребява — за прости стилове е достатъчно да се конфигурират стандартните компоненти чрез API за външен вид.

Персонализирани изгледи на iOS: drawRect и Core Graphics

На iOS персонализираните изгледи се създават чрез наследяване на UIView и презаписване на метода drawRect. drawRect се извиква при първото рендериране и след всяко извикване на setNeedsDisplay(). Вътре в drawRect разработчикът получава CGContext чрез UIGraphicsGetCurrentContext() — платно за линии, форми, градиенти и текст. Core Graphics (Quartz 2D) е ниско ниво CPU-базиран двигател за рендериране, който дава пълен контрол над всеки пиксел. UIBezierPath е удобна обвивка за създаване на пътища с кратък синтаксис.

swift
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: CGContext, CGGradient и трансформации

Core Graphics предоставя CGContext — платно за всички операции по рисуване. CGGradient създава линейни и радиални градиенти с поддръжка на CGColorSpace (sRGB, Display P3). Трансформациите се извършват чрез CGAffineTransform — матрица 3x3 за завъртане, мащабиране и преместване. CGContextTranslateCTM, CGContextRotateCTM и CGContextScaleCTM променят координатната система. Core Graphics работи на CPU, така че сложната графика може да натовари процесора — използвайте Metal за GPU ускорение.

UIBezierPath за създаване на форми

UIBezierPath е обектно-ориентирана обвивка над CGPath. Методът addArc(withCenter:radius:startAngle:endAngle:clockwise:) създава дъги и кръгове, addCurve създава криви на Безие. Пътищата поддържат операции обединение, сечение и изваждане чрез addClip. UIBezierPath е удобен за персонализирани маски (maskView), изрязващи пътища и сложни форми — звезди, сърца, персонализирани икони.

Персонализирани изгледи на Android: onDraw и Canvas

На Android персонализираният изглед разширява View с презаписан onDraw(Canvas). Canvas съдържа всички методи за рисуване в мобилната разработка: drawCircle, drawRect, drawLine, drawText, drawBitmap, drawPath и drawRoundRect. Paint конфигурира параметри — цвят, дебелина на линията, стил (FILL, STROKE, FILL_AND_STROKE), изглаждане (isAntiAlias) и размер на текста. onDraw се извиква при всяко invalidate() и не трябва да съдържа тежки операции — всички изчисления се кешират.

kotlin
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 и анимации на Android

Path на Android е еквивалент на UIBezierPath: addCircle, addRect, addOval, lineTo, cubicTo и quadTo. PathMeasure изчислява дължината на пътя и координатите във всяка точка — полезно за анимиране на движение на обект по път. За анимации се използва ValueAnimator с invalidate() в обратното извикване. Аниматорът може да променя цвят, радиус, позиция — всяко свойство, което влияе на рисуването. Персонализираните изгледи на Android също поддържат StateListDrawable и animated-vector за анимация чрез XML.

Shader и градиенти в Canvas

Градиентите на Android се задават чрез Shader — LinearGradient, RadialGradient и SweepGradient. Shader се присвоява на Paint чрез paint.setShader(shader). LinearGradient генерира линеен градиент между две точки с опционални позиции на цветовете. RadialGradient — радиален от центъра към ръбовете. SweepGradient — коничен около централна точка. Shader.TileMode (CLAMP, REPEAT, MIRROR) определя поведението извън границите на областта.

CustomPainter във Flutter: рисуване на Canvas

Flutter използва CustomPainter — клас с методи paint(Canvas canvas, Size size) и shouldRepaint. Canvas във Flutter предоставя същите методи като в Android: drawCircle, drawRect, drawLine, drawPath, drawParagraph и drawImage. Paint във Flutter конфигурира цвят, дебелина, стил и изглаждане. Flutter не използва drawRect или onDraw — цялото рисуване става чрез CustomPainter, вграден в джаджата CustomPaint.

dart
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 и RepaintBoundary

shouldRepaint определя дали CustomPainter трябва да бъде прерисуван. Връщайте true само когато данните, влияещи на рендерирането, се променят — цвят, размер, данни на графиката. RepaintBoundary изолира прерисуването в отделен слой — използвайте за джаджи, които рядко се променят. Flutter няма setNeedsDisplay или invalidate — прерисуването се задейства чрез setState или ValueNotifier с проследяване на промени.

Градиенти и трансформации във Flutter

Flutter поддържа LinearGradient, RadialGradient и SweepGradient — същите типове като в Android. Gradient създава Shader за Paint чрез createShader(Rect bounds). Трансформациите се извършват чрез canvas.rotate, canvas.scale, canvas.translate и canvas.skew. Flutter използва матрица на трансформация 4x4 (Matrix4) за джаджата Transform. Анимациите на рисуване във Flutter се правят чрез AnimationController в комбинация с setState за прерисуване на CustomPainter.

Измерване на персонализирани изгледи: методи sizeThatFits, onMeasure и computeDryLayout

Правилното измерване на персонализираните изгледи е основата на предвидимото поведение на интерфейса. На iOS размерът на Изгледа се определя чрез sizeThatFits и intrinsicContentSize. sizeThatFits връща оптималния размер за дадени ограничения. intrinsicContentSize — естественият размер на съдържанието без външни ограничения. На Android измерването се реализира в onMeasure с параметри MeasureSpec (UNSPECIFIED, EXACTLY, AT_MOST). Във Flutter размерът се предава на paint(Canvas, Size) и може да се изчисли чрез computeDryLayout или LayoutBuilder.

sizeThatFits и intrinsicContentSize на iOS

intrinsicContentSize връща CGSize — естествения размер на Изгледа въз основа на неговото съдържание. setContentHuggingPriority и setContentCompressionResistancePriority контролират поведението при разтягане и компресиране. sizeThatFits се извиква от системата за изчисляване на размера в Auto Layout. За персонализирани изгледи презапишете intrinsicContentSize, ако вашият компонент има естествен размер — например, кръг винаги трябва да бъде 100x100.

onMeasure и MeasureSpec на Android

onMeasure приема widthMeasureSpec и heightMeasureSpec. MeasureSpec съдържа режим и размер: UNSPECIFIED (без ограничения, Изгледът сам избира размера си), EXACTLY (точен размер от родителя), AT_MOST (максимален размер). setMeasuredDimension(width, height) запазва резултата от измерването. При промяна на данни извикайте requestLayout() за повторно измерване. Вложените ViewGroup изискват презаписване на onLayout за подреждане на дъщерните елементи.

ПлатформаМетод за измерванеИзвикване при промянаВръщане
iOSsizeThatFits / intrinsicContentSizesetNeedsLayout / invalidateIntrinsicContentSizeCGSize
AndroidonMeasure / setMeasuredDimensionrequestLayout / invalidatevoid (запазва размер)
FluttercomputeDryLayoutsetState / LayoutBuilderSize

computeDryLayout във Flutter

computeDryLayout е метод на RenderObject за изчисляване на размер без пълен цикъл на оформление. LayoutBuilder.getSize — алтернатива за получаване на налично пространство в build метода. Във Flutter размерът на платното се предава на paint като Size и не изисква отделно измерване — CustomPainter рисува в рамките на предадените граници. Въпреки това, за персонализирани RenderObject трябва да презапишете performLayout и computeDryLayout.

Често задавани въпроси

Какво е drawRect на iOS и кога се извиква?

drawRect е метод на UIView за персонализирано рисуване чрез Core Graphics. Извиква се при първото рендериране на Изгледа и след всяко извикване на setNeedsDisplay(). Използвайте CGContext вътре в drawRect за линии, форми и текст.

Как да рисуваме на Android с помощта на Canvas?

Създайте клас, който разширява View, презапишете onDraw(Canvas canvas) и използвайте Canvas API: drawCircle, drawRect, drawPath. Paint конфигурира цвят, дебелина и стил. За актуализация извикайте invalidate().

Какво е CustomPainter във Flutter?

CustomPainter е клас на Flutter за персонализирано рисуване на Canvas. Имплементирайте методите paint(Canvas, Size) и shouldRepaint. Поставя се чрез джаджата CustomPaint. Flutter няма drawRect — цялото рисуване става чрез CustomPainter.

Как да измерим размера на персонализиран изглед?

На iOS използвайте sizeThatFits и intrinsicContentSize. На Android — onMeasure с MeasureSpec. Във Flutter размерът се предава на paint(Canvas, Size) или се изчислява чрез computeDryLayout. Всяка платформа използва свой собствен метод за измерване.

Кога да използваме персонализирани изгледи вместо стандартни компоненти?

Персонализираните изгледи са необходими за уникална графика, анимации, графики и елементи, които не могат да бъдат реализирани със стандартен UIKit или View. За прости стилове е достатъчно да конфигурирате стандартните компоненти — не усложнявайте архитектурата без необходимост.

Резюме

  • Персонализирани изгледи — основа на уникални интерфейси за графики, анимации и нестандартни елементи в мобилни приложения.
  • drawRect — iOS метод за рисуване чрез Core Graphics с CGContext и UIBezierPath.
  • onDraw — Android метод за рисуване чрез Canvas и Paint с поддръжка на Path и Shader.
  • CustomPainter — Flutter клас за рисуване на Canvas с shouldRepaint и RepaintBoundary.
  • Измерване — валидация на размери чрез sizeThatFits (iOS), onMeasure (Android) и computeDryLayout (Flutter).
  • Рисуването в мобилната разработка следва единен модел на всички платформи: получаване на контекст, конфигуриране на стилове и рисуване на примитиви.
  • Кеширайте обекти за рисуване (Paint, Path) — не ги създавайте вътре в drawRect, onDraw или paint за стабилна производителност.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта