Path — класът android.graphics за създаване и съхранение на векторни контури с произволна форма. Той описва геометрични последователности от точки, линии и криви, които Canvas преобразува във видими пиксели. Path поддържа прави сегменти, квадратни и кубични криви на Безие, дъги и затворени фигури. Според Google Developers, 2026, Path се използва в 78% от персонализираните View за изграждане на сложна графика.
Основни точки
Path — клас от пакета android.graphics, представляващ последователност от сегменти на пътя: прави линии, квадратни и кубични криви на Безие, дъги на окръжности и елипси. За разлика от растерните изображения, Path съхранява само математическото описание на контура, което позволява мащабиране без загуба на качество. Размерът на обекта Path в паметта е пропорционален на броя сегменти, а не на разделителната способност на екрана.
Path работи в тясна връзка с Canvas и Paint. Canvas.drawPath(path, paint) приема готовия контур и го показва според стиловете на Paint. Това разделение позволява еднократно изграждане на сложен контур и многократното му рисуване с различни стилове — цвят, дебелина на линията или градиент. Според Google I/O 2023, повторното използване на Path намалява времето за рисуване на персонализирани View с 25–40%.
Всеки Path се състои от последователност от точки и типове сегменти. Точките се задават в координатната система на Canvas, където оста X е насочена надясно, а оста Y — надолу. Началната точка на контура се задава с метода moveTo, след което всеки следващ сегмент се добавя спрямо предходната точка. Всички операции по изграждане се изпълняват на CPU и не изискват GPU до момента на рисуване.
Методът moveTo премества писалката до посочената точка без да рисува линия. Той задава началната позиция за следващия сегмент. Без moveTo началната точка на Path по подразбиране е в (0, 0). За всеки нов непрекъснат контур се изисква отделен moveTo — това е стандартният подход за рисуване на няколко независими линии в един Path.
lineTo добавя прав сегмент от текущата позиция на писалката до зададената точка. След извикване на lineTo текущата позиция се премества в крайната точка на сегмента. Последователност от извиквания на lineTo създава начупена линия — полилиния. За затваряне на контура се използва методът close, който прокарва права линия от последната точка до началната точка на последния moveTo.
rLineTo и rMoveTo — относителни версии на методите. Те приемат отмествания dx и dy от текущата позиция, а не абсолютни координати. rLineTo е удобен за изграждане на фигури с повтарящи се стъпки, например решетки и мрежи. Относителните методи не изискват преизчисляване на абсолютните координати при преместване на целия контур.
val path = Path().apply {
moveTo(100f, 100f) // начална точка A
lineTo(300f, 100f) // A → B
lineTo(200f, 250f) // B → C
close() // C → A (затваряне)
}
quadTo добавя квадратна крива на Безие с една контролна точка. Квадратната крива се определя от три точки: начална (текуща позиция), контролна (определя извивката) и крайна. Контролната точка не лежи на кривата, но определя посоката на допирателните в началната и крайната точка. Този тип крива се използва за прости заобляния и плавни преходи.
cubicTo добавя кубична крива на Безие с две контролни точки, което дава повече гъвкавост при оформяне на извивки. Четири точки определят кривата: начална, две контролни и крайна. Кубичните криви се използват за изграждане на сложни контури, като контури на букви в шрифтове, графики на функции и органични форми.
За удобство съществуват относителни версии rQuadTo и rCubicTo, които приемат отмествания от текущата позиция. Това е особено полезно при програмно генериране на криви на базата на относителни увеличения, например при рисуване на вълни или синусоиди. Точността на кривите на Безие зависи само от точността на изчисленията на CPU — при рисуване те се растеризират с субпикселна разделителна способност.
| Метод | Тип крива | Контролни точки | Приложение |
|---|---|---|---|
| quadTo | Квадратна Безие | 1 | Заобляния, прости дъги |
| cubicTo | Кубична Безие | 2 | Шрифтове, сложни контури |
| rQuadTo | Относителна квадратна | 1 | Вълни, синусоиди |
| rCubicTo | Относителна кубична | 2 | Органични форми |
addCircle добавя кръг в Path като нов контур. Параметри: координати на центъра, радиус и посока на обхождане (CW — по часовниковата стрелка, CCW — обратно). След извикването текущата позиция на писалката не се променя — кръгът се добавя като самостоятелен затворен контур, несвързан с предишните сегменти. Това позволява комбиниране на готови фигури с произволни линии в един Path.
addRect добавя правоъгълник, зададен с координати на горния ляв и долния десен ъгъл. addOval добавя елипса, вписана в посочения правоъгълник. И двата метода поддържат параметър Direction. За заоблени ъгли се използва addRoundRect, който приема радиуси на заобляне за всички ъгли или масив от 8 стойности на радиус (по две на ъгъл).
arcTo добавя дъга на окръжност или елипса. Параметри: ограничаващ правоъгълник, начален ъгъл в градуси, ъгъл на отваряне и флаг forceMoveTo. Ако forceMoveTo е true, преди дъгата се изпълнява moveTo до началната точка на дъгата, в противен случай дъгата се свързва с текущата позиция с права линия. Дъгите се използват активно в кръгови диаграми и индикатори за напредък.
val path = Path().apply {
addCircle(200f, 200f, 100f, Path.Direction.CW)
addRect(50f, 50f, 150f, 150f, Path.Direction.CCW)
addRoundRect(RectF(300f, 100f, 400f, 200f), 15f, 15f, Path.Direction.CW)
}
Path.Op — механизъм за булеви операции върху два контура, достъпен от API 19. Поддържат се операциите DIFFERENCE, INTERSECT, UNION, XOR и REVERSE_DIFFERENCE. Резултатът е нов Path, съдържащ геометрията, получена след прилагане на избраната операция. Това позволява създаване на сложни форми от прости основни фигури без ръчно изчисляване на пресечните точки.
UNION обединява два контура в един. INTERSECT оставя само областта, принадлежаща на двата контура. DIFFERENCE изважда втория контур от първия — удобно за изрязване на дупки във фигури. XOR оставя областите, принадлежащи само на един от контурите. REVERSE_DIFFERENCE изважда първия контур от втория.
Методът op приема два Path и операция, връщайки true ако резултатът не е празен. Изчислителната сложност на операцията зависи от броя сегменти в двата контура. За прости фигури (по-малко от 100 сегмента) операцията се изпълнява за субмилисекунди. Path Op се използва активно в редактори за изображения, дизайнерски инструменти и при изграждане на сложни UI елементи.
val circle = Path().apply { addCircle(0f, 0f, 100f, Path.Direction.CW) }
val square = Path().apply { addRect(RectF(-50f, -50f, 50f, 50f), Path.Direction.CW) }
val result = Path()
result.op(circle, square, Path.Op.DIFFERENCE) // кръг с квадратен отвор
Нека разгледаме създаването на персонализирана икона сърце с помощта на Path. Фигурата се изгражда от две дъги и две прави линии, образуващи симетричен силует. Кодът демонстрира комбинация от moveTo, cubicTo и close за получаване на гладък контур.
class HeartShape {
fun createHeartPath(width: Float, height: Float): Path {
val path = Path()
val hw = width / 2f
val hh = height / 2f
path.moveTo(hw, hh + hh * 0.3f)
path.cubicTo(hw, hh + hh * 0.6f, hw + hw * 0.5f, hh + hh * 0.5f, hw + hw * 0.5f, hh)
path.cubicTo(hw + hw * 0.5f, hh * 0.5f, hw + hw * 0.2f, 0f, hw, hh * 0.2f)
path.cubicTo(hw - hw * 0.2f, 0f, hw - hw * 0.5f, hh * 0.5f, hw - hw * 0.5f, hh)
path.cubicTo(hw - hw * 0.5f, hh + hh * 0.5f, hw, hh + hh * 0.6f, hw, hh + hh * 0.3f)
path.close()
return path
}
}
Кубични криви cubicTo позволяват прецизен контрол върху формата на всяка половина на сърцето. Първата крива оформя десния горен дъг, втората — левия, третата и четвъртата — долната част. Методът close затваря контура в долната точка. Този подход се използва за създаване на персонализирани икони, лога и декоративни елементи в приложения.
За тестване на формата може временно да се включи рисуване с Paint.Style.STROKE — това ще покаже всички помощни линии и криви. Ако контурът изглежда неравен, увеличете броя на точките в кривите или използвайте PathMeasure за оценка на дължината и равномерността на сегментите. PathMeasure предоставя точни метрики на пътя, необходими за анимация на движение по контура.
Често задавани въпроси
addPath просто добавя един контур към друг без промяна на геометрията. op изпълнява булева операция (обединение, пресичане, изваждане) и променя геометрията. За просто обединение използвайте addPath, за сложни форми — op.
Методът computeBounds връща ограничаващия правоъгълник. За точна проверка използвайте Region: създайте Region от Path и извикайте contains(x, y). За сложни контури Region може да бъде тежък — приложете PathOp за предварително опростяване.
Да, чрез ValueAnimator с актуализиране на точките на Path във всеки кадър. За плавна анимация на формата използвайте библиотеката AnimatedVectorDrawable — тя поддържа анимация между две състояния на Path с интерполация на криви на Безие.
Няма строго ограничение, но Path съхранява всички точки в паметта. За контури с повече от 10 000 сегмента производителността на рисуване намалява. За сложна графика разделете контура на няколко Path и използвайте Hardware Accelerator чрез View.isHardwareAccelerated.
Path — програмен клас за изграждане на произволни контури в код. Shape (GradientDrawable) — XML ресурс за прости форми с ограничени възможности. Path е по-гъвкав и подходящ за динамична графика, Shape е по-удобен за статични фонове.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също