Path в Android — что это, методы построения и как рисовать

Автор: IT Sectr Опубликовано: 2026-07-21 Время чтения: 8 мин

Path — класс android.graphics для создания и хранения векторных контуров произвольной формы. Он описывает геометрические последовательности точек, линий и кривых, которые Canvas преобразует в видимые пиксели. Path поддерживает прямые отрезки, квадратичные и кубические кривые Безье, дуги и замкнутые фигуры. По данным Google Developers, 2026, Path используется в 78% кастомных View для построения нетривиальной графики.

Главное

  • Path — векторный контур, задающий последовательность геометрических операций для рисования.
  • moveTo, lineTo, quadTo и cubicTo — базовые методы построения линий и кривых.
  • addCircle, addRect, addOval — готовые формы для быстрого добавления фигур.
  • close замыкает контур, соединяя последнюю точку с первой прямой линией.
  • Op (Path.Op) позволяет выполнять булевы операции: объединение, пересечение, вычитание контуров.

Что такое Path в Android?

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 и lineTo

Метод moveTo перемещает перо в указанную точку без рисования линии. Он задаёт начальную позицию для следующего сегмента. Без moveTo начальная точка Path по умолчанию находится в (0, 0). Для каждого нового непрерывного контура требуется отдельный moveTo — это стандартный подход для рисования нескольких независимых линий в одном Path.

lineTo — прямая линия

lineTo добавляет прямой отрезок от текущей позиции пера до заданной точки. После вызова lineTo текущая позиция перемещается в конечную точку отрезка. Последовательность lineTo вызовов создаёт ломаную линию — полилинию. Для замыкания контура используется метод close, который проводит прямую линию от последней точки к начальной точке последнего moveTo.

rLineTo и rMoveTo — относительные версии методов. Они принимают смещения dx и dy от текущей позиции, а не абсолютные координаты. rLineTo удобен для построения фигур с повторяющимися шагами, например решёток и сеток. Относительные методы не требуют пересчёта абсолютных координат при смещении всего контура.

kotlin
val path = Path().apply {
    moveTo(100f, 100f)     // start point A
    lineTo(300f, 100f)     // A -> B
    lineTo(200f, 250f)     // B -> C
    close()                    // C -> A (close)
}

Кривые Безье: quadTo и cubicTo

quadTo добавляет квадратичную кривую Безье с одной контрольной точкой. Квадратичная кривая определяется тремя точками: начальной (текущая позиция), контрольной (определяет изгиб) и конечной. Контрольная точка не лежит на кривой, но задаёт направление касательных в начальной и конечной точках. Этот тип кривой используется для простых скруглений и плавных переходов.

cubicTo — кубическая кривая Безье

cubicTo добавляет кубическую кривую Безье с двумя контрольными точками, что даёт больше гибкости при формировании изгибов. Четыре точки определяют кривую: начальная, две контрольные и конечная. Кубические кривые применяются для построения сложных контуров, таких как контуры букв в шрифтах, графики функций и органические формы.

Для удобства существуют относительные версии rQuadTo и rCubicTo, принимающие смещения от текущей позиции. Это особенно полезно при программной генерации кривых на основе относительных приращений, например при рисовании волн или синусоид. Точность кривых Безье зависит только от точности вычислений на CPU — при отрисовке они растеризуются с субпиксельным разрешением.

МетодТип кривойКонтрольных точекПрименение
quadToКвадратичная Безье1Скругления, простые дуги
cubicToКубическая Безье2Шрифты, сложные контуры
rQuadToОтносительная квадратичная1Волны, синусоиды
rCubicToОтносительная кубическая2Органические формы

Готовые фигуры: окружности, прямоугольники и дуги

addCircle добавляет окружность в Path как новый контур. Параметры: координаты центра, радиус и направление обхода (CW — по часовой, CCW — против часовой). После вызова текущая позиция пера не изменяется — окружность добавляется как самостоятельный замкнутый контур, не связанный с предыдущими сегментами. Это позволяет комбинировать готовые фигуры с произвольными линиями в одном Path.

addRect и addOval

addRect добавляет прямоугольник, заданный координатами левого верхнего и правого нижнего углов. addOval добавляет эллипс, вписанный в указанный прямоугольник. Оба метода поддерживают параметр Direction. Для скруглённых углов используется addRoundRect, который принимает радиусы скругления для всех углов или массив из 8 значений радиуса (по два на угол).

arcTo добавляет дугу окружности или эллипса. Параметры: ограничивающий прямоугольник, начальный угол в градусах, угол разворота и флаг forceMoveTo. Если forceMoveTo равен true, перед дугой выполняется moveTo к начальной точке дуги, иначе дуга соединяется с текущей позицией прямой линией. Дуги активно используются в круговых диаграммах и прогресс-индикаторах.

kotlin
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)

Path.Op — механизм булевых операций над двумя контурами, доступный начиная с API 19. Поддерживаются операции DIFFERENCE, INTERSECT, UNION, XOR и REVERSE_DIFFERENCE. Результатом является новый Path, содержащий геометрию, полученную после применения выбранной операции. Это позволяет создавать сложные формы из простых базовых фигур без ручного расчёта точек пересечений.

Применение Path Op в дизайне

UNION объединяет два контура в один. INTERSECT оставляет только область, принадлежащую обоим контурам. DIFFERENCE вычитает второй контур из первого — удобно для вырезания «дырок» в фигурах. XOR оставляет области, принадлежащие только одному из контуров. REVERSE_DIFFERENCE вычитает первый контур из второго.

Метод op принимает два Path и операцию, возвращая true если результат не пустой. Вычислительная сложность операции зависит от количества сегментов в обоих контурах. Для простых фигур (менее 100 сегментов) операция выполняется за субмиллисекунды. Path Op активно применяется в редакторах изображений, дизайнерских инструментах и при построении сложных UI-элементов.

kotlin
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) // circle with square hole

Пример построения сложной фигуры

Рассмотрим создание кастомной иконки «сердце» с помощью Path. Фигура строится из двух дуг и двух прямых линий, образующих симметричный силуэт. Код демонстрирует комбинацию moveTo, cubicTo и close для получения плавного контура.

kotlin
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 выполняет булеву операцию (объединение, пересечение, вычитание) и изменяет геометрию. Для простого слияния используйте addPath, для сложных форм — op.

Как проверить, содержит ли Path точку?

Метод computeBounds возвращает ограничивающий прямоугольник. Для точной проверки используйте Region: создайте Region из Path и вызовите contains(x, y). Для сложных контуров Region может быть тяжёлым — применяйте PathOp для предварительного упрощения.

Можно ли анимировать Path?

Да, через ValueAnimator с обновлением точек Path в каждом кадре. Для плавной анимации формы используйте библиотеку AnimatedVectorDrawable — она поддерживает анимацию между двумя состояниями Path с интерполяцией кривых Безье.

Какой максимальный размер Path?

Жёсткого ограничения нет, но Path хранит все точки в памяти. Для контуров с более чем 10 000 сегментов производительность отрисовки снижается. Для сложной графики разделите контур на несколько Path и используйте Hardware Accelerator через View.isHardwareAccelerated.

Чем отличается Path от Shape в Android?

Path — программный класс для построения произвольных контуров в коде. Shape (GradientDrawable) — XML-ресурс для простых форм с ограниченными возможностями. Path гибче и подходит для динамической графики, Shape удобнее для статичных фонов.

Итоги

  • Path — векторный контур для описания произвольных геометрических форм в Android.
  • moveTo задаёт начальную точку, lineTo рисует прямые, quadTo и cubicTo — кривые Безье.
  • addCircle, addRect, addOval и addRoundRect добавляют готовые фигуры.
  • close замыкает контур, соединяя последнюю и первую точки.
  • Path.Op предоставляет булевы операции: UNION, INTERSECT, DIFFERENCE, XOR.
  • Создавайте Path однократно и переиспользуйте для экономии ресурсов CPU.
  • Используйте PathMeasure для анимации вдоль контура и оценки длины пути.

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

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также