Многим приложениям необходимо точно контролировать то, что отображается на экране. Это может быть что-то незначительное, например, размещение прямоугольника или круга на экране в нужном месте, или же сложная комбинация графических элементов в различных стилях.
Базовое рисование с использованием модификаторов и DrawScope
Основной способ отрисовки пользовательского объекта в Compose — использование модификаторов, таких как Modifier.drawWithContent , Modifier.drawBehind и Modifier.drawWithCache .
Например, чтобы нарисовать что-либо за вашим составным объектом, вы можете использовать модификатор drawBehind для начала выполнения команд рисования:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
Если вам нужен только элемент, который рисует, вы можете использовать элемент Canvas . Canvas — это удобная обертка над Modifier.drawBehind . Вы размещаете Canvas в своем макете так же, как и любой другой элемент Compose UI. Внутри Canvas вы можете рисовать элементы, точно контролируя их стиль и местоположение.
Все модификаторы рисования предоставляют объект DrawScope — ограниченную среду рисования, которая поддерживает собственное состояние. Это позволяет задавать параметры для группы графических элементов. DrawScope предоставляет несколько полезных полей, таких как size — объект Size , определяющий текущие размеры DrawScope .
Для рисования можно использовать одну из множества функций рисования в DrawScope . Например, следующий код рисует прямоугольник в верхнем левом углу экрана:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F drawRect( color = Color.Magenta, size = canvasQuadrantSize ) }

Чтобы узнать больше о различных модификаторах рисования, см. документацию по графическим модификаторам .
система координат
Чтобы нарисовать что-либо на экране, необходимо знать смещение ( x и y ) и размер элемента. Во многих методах рисования в DrawScope положение и размер задаются значениями параметров по умолчанию . Параметры по умолчанию обычно позиционируют элемент в точке [0, 0] на холсте и задают size по умолчанию, который заполняет всю область рисования, как в приведенном выше примере — вы можете видеть, что прямоугольник расположен в верхнем левом углу. Чтобы настроить размер и положение элемента, необходимо понимать систему координат в Compose.
Начало координат ( [0,0] ) находится в самом верхнем левом пикселе области рисования. Величина x увеличивается при движении вправо, а величина y — при движении вниз.
![Сетка, отображающая систему координат, показывающую верхний левый угол [0, 0] и нижний правый угол [ширина, высота].](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_coordinate_system_drawing.png?authuser=4&hl=ru)
Например, если вы хотите нарисовать диагональную линию от верхнего правого угла области холста до нижнего левого угла, вы можете использовать функцию DrawScope.drawLine() и указать начальное и конечное смещение с соответствующими координатами x и y:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasWidth = size.width val canvasHeight = size.height drawLine( start = Offset(x = canvasWidth, y = 0f), end = Offset(x = 0f, y = canvasHeight), color = Color.Blue ) }
Основные преобразования
DrawScope предлагает преобразования для изменения места или способа выполнения команд рисования.
Шкала
Используйте DrawScope.scale() для увеличения размера операций рисования в несколько раз. Операции, подобные scale() применяются ко всем операциям рисования в рамках соответствующей лямбда-функции. Например, следующий код увеличивает scaleX в 10 раз и scaleY в 15 раз:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }

Переводить
Используйте DrawScope.translate() для перемещения объекта рисования вверх, вниз, влево или вправо. Например, следующий код перемещает объект рисования на 100 пикселей вправо и на 300 пикселей вверх:
Canvas(modifier = Modifier.fillMaxSize()) { translate(left = 100f, top = -300f) { drawCircle(Color.Blue, radius = 200.dp.toPx()) } }

Повернуть
Используйте DrawScope.rotate() для поворота графического элемента вокруг опорной точки. Например, следующий код поворачивает прямоугольник на 45 градусов:
Canvas(modifier = Modifier.fillMaxSize()) { rotate(degrees = 45F) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }

rotate() для применения поворота к текущей области рисования, в результате чего прямоугольник поворачивается на 45 градусов.Вставка
Используйте DrawScope.inset() для настройки параметров по умолчанию текущего объекта DrawScope , изменяя границы чертежа и соответствующим образом перемещая чертежи:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
Этот код фактически добавляет отступы к командам рисования:

Множественные преобразования
Для применения нескольких преобразований к вашим чертежам используйте функцию DrawScope.withTransform() , которая создает и применяет единое преобразование, объединяющее все необходимые изменения. Использование withTransform() более эффективно, чем вложенные вызовы отдельных преобразований, поскольку все преобразования выполняются вместе в одной операции, вместо того чтобы Compose вычислял и сохранял каждое из вложенных преобразований.
Например, следующий код применяет к прямоугольнику как перемещение, так и вращение:
Canvas(modifier = Modifier.fillMaxSize()) { withTransform({ translate(left = size.width / 5F) rotate(degrees = 45F) }) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }

withTransform , чтобы применить как вращение, так и перемещение, повернув прямоугольник и сдвинув его влево.Типичные операции черчения
Нарисовать текст
Для отрисовки текста в Compose обычно можно использовать компонент Text . Однако, если вы находитесь в DrawScope или хотите отрисовать текст вручную с возможностью настройки, вы можете использовать метод DrawScope.drawText() .
Для отрисовки текста создайте TextMeasurer , используя rememberTextMeasurer , и вызовите drawText с этим объектом:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }

Измерить текст
Рисование текста работает несколько иначе, чем другие команды рисования. Обычно вы задаете команде рисования размер (ширину и высоту), в котором будет нарисована фигура/изображение. В случае с текстом существует несколько параметров, которые управляют размером отображаемого текста, таких как размер шрифта, сам шрифт, лигатуры и межбуквенный интервал.
В Compose вы можете использовать TextMeasurer для получения измеренного размера текста в зависимости от вышеуказанных факторов. Если вы хотите нарисовать фон за текстом, вы можете использовать измеренную информацию, чтобы получить размер области, которую занимает текст:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()), style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
Этот фрагмент кода создает розовый фон для текста:

Изменение ограничений, размера шрифта или любого свойства, влияющего на измеряемый размер, приводит к изменению отображаемого размера. Вы можете установить фиксированный размер как для width , так и height , и текст будет следовать за заданным значением TextOverflow . Например, следующий код отображает текст на ⅓ высоты и ⅓ ширины компонуемой области и устанавливает TextOverflow равным TextOverflow.Ellipsis :
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixed( width = (size.width / 3f).toInt(), height = (size.height / 3f).toInt() ), overflow = TextOverflow.Ellipsis, style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
Теперь текст отображается в рамках заданных ограничений с многоточием в конце:

TextOverflow.Ellipsis с фиксированными ограничениями на измерение текста.Нарисуйте изображение
Чтобы нарисовать ImageBitmap с помощью DrawScope , загрузите изображение, используя ImageBitmap.imageResource() , а затем вызовите drawImage :
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) Canvas(modifier = Modifier.fillMaxSize(), onDraw = { drawImage(dogImage) })

ImageBitmap на холсте.Нарисуйте основные геометрические фигуры.
В DrawScope есть множество функций для рисования фигур. Чтобы нарисовать фигуру, используйте одну из предопределенных функций рисования, например, drawCircle :
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
API | Выход |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
Нарисовать контур
Путь — это последовательность математических инструкций, выполнение которых приводит к созданию рисунка. DrawScope может нарисовать путь с помощью метода DrawScope.drawPath() .
Например, предположим, вы хотите нарисовать треугольник. Вы можете создать контур с помощью таких функций, как lineTo() и moveTo() используя размер области рисования. Затем вызовите функцию drawPath() с этим только что созданным контуром, чтобы получить треугольник.
Spacer( modifier = Modifier .drawWithCache { val path = Path() path.moveTo(0f, 0f) path.lineTo(size.width / 2f, size.height / 2f) path.lineTo(size.width, 0f) path.close() onDrawBehind { drawPath(path, Color.Magenta, style = Stroke(width = 10f)) } } .fillMaxSize() )

Path в Compose. Доступ к объекту Canvas
При использовании DrawScope у вас нет прямого доступа к объекту Canvas . Вы можете использовать DrawScope.drawIntoCanvas() , чтобы получить доступ к самому объекту Canvas , на котором можно вызывать функции.
Например, если у вас есть собственный объект Drawable , который вы хотите нарисовать на холсте, вы можете получить доступ к холсту и вызвать Drawable#draw() , передав в него объект Canvas :
val drawable = ShapeDrawable(OvalShape()) Spacer( modifier = Modifier .drawWithContent { drawIntoCanvas { canvas -> drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt()) drawable.draw(canvas.nativeCanvas) } } .fillMaxSize() )

Drawable .Узнать больше
Для получения более подробной информации о программе Drawing in Compose, ознакомьтесь со следующими ресурсами:
- Графические модификаторы — узнайте о различных типах графических модификаторов.
- Кисть — научитесь настраивать параметры отрисовки контента.
- Пользовательские макеты и графика в Compose — Android Dev Summit 2022 — Узнайте, как создать пользовательский интерфейс в Compose с помощью макетов и графики.
- Пример JetLagged Sample - Compose Sample, демонстрирующий, как построить пользовательский график.
Рекомендуем вам
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Модификаторы графики
- Графика в композиции
- Линии выравнивания в Jetpack Compose






