В этом уроке:
- используем clip
Обычно нам для рисования доступна вся канва. Но бывают случаи, когда надо нарисовать объект так, чтобы прорисовалась только какая-то его часть, а остальное – нет.
Из жизни можно провести аналогию с двумя бумажными листами. Кладем один лист на стол. А во втором вырезаем отверстие нужной нам формы и кладем второй лист поверх на первый. Далее полностью закрашиваем второй лист краской и убираем его. В итоге получаем на первом листе нужную нам форму ровно закрашенную.
Вот что-то подобное делает clip. Он на канве определяет область, где рисование будет работать. А в остальных местах ничего рисоваться не будет.
Создадим проект:
Project name: P1481_CanvasClip
Build Target: Android 2.3.3
Application name: CanvasClip
Package name: ru.startandroid.develop.p1481canvasclip
Create Activity: MainActivity
MainActivity.java:
package ru.startandroid.develop.p1481canvasclip;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends View {
Paint p;
Rect rect;
public DrawView(Context context) {
super(context);
p = new Paint();
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(3);
rect = new Rect(210, 210, 410, 510);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
// сетка
p.setColor(Color.BLUE);
drawGrid(canvas);
// красный прямоугольник
p.setColor(Color.RED);
canvas.drawRect(rect, p);
}
private void drawGrid(Canvas canvas) {
for (int i = 25; i < 400; i += 25) {
canvas.drawLine(100 + i, 100, 100 + i, 600, p);
}
for (int i = 25; i < 500; i += 25) {
canvas.drawLine(100, 100 + i, 500, 100 + i, p);
}
}
}
}
Просто выводим на экран сетку из линий синим цветом и прямоугольник rect красным цветом.
Результат:

Изменим пример так, чтобы красный прямоугольник ограничивал область рисования на канве.
Перепишем onDraw:
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
// сетка
p.setColor(Color.BLUE);
drawGrid(canvas);
// красный прямоугольник
p.setColor(Color.RED);
canvas.drawRect(rect, p);
// смещение
canvas.translate(600, 0);
// задание clip-области
canvas.clipRect(rect);
// сетка
p.setColor(Color.BLUE);
drawGrid(canvas);
}
Мы снова выводим синие линии и красный прямоугольник. Затем смещаемся вправо и вместо рисования красного прямоугольника мы методом clipRect говорим канве, что теперь рисование доступно только в этой области. И рисуем синие линии.
Результат:

Видим, что справа линии нарисовались только в области rect, т.к. мы задали это методом clipRect.
Разумеется, clip-область будет работать только для последующих рисований. Все, что было нарисовано до задания этой области, остается как было.
При задании clip-области мы можем использовать несколько прямоугольников. Для добавления прямоугольников используется эта версия метода: clipRect(Rect rect, Region.Op op). Здесь используются режимы взаимодействия областей, которые мы подробно рассмотрели в прошлом уроке про регионы.
Посмотрим на примере. Перепишем класс DrawView:
class DrawView extends View {
Paint p;
Rect rect1;
Rect rect2;
Region.Op op = Region.Op.UNION;
public DrawView(Context context) {
super(context);
p = new Paint();
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(3);
rect1 = new Rect(180, 220, 340, 380);
rect2 = new Rect(280, 320, 440, 480);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
// сетка
p.setColor(Color.BLUE);
drawGrid(canvas);
// красные прямоугольники
p.setColor(Color.RED);
canvas.drawRect(rect1, p);
canvas.drawRect(rect2, p);
// смещение
canvas.translate(600, 0);
// задание clip-области
canvas.clipRect(rect1);
canvas.clipRect(rect2, op);
// сетка
p.setColor(Color.BLUE);
drawGrid(canvas);
}
private void drawGrid(Canvas canvas) {
for (int i = 25; i < 400; i += 25) {
canvas.drawLine(100 + i, 100, 100 + i, 600, p);
}
for (int i = 25; i < 500; i += 25) {
canvas.drawLine(100, 100 + i, 500, 100 + i, p);
}
}
}
При использовании UNION, области прямоугольников объединились в одну область и она стала clip-областью.
Результат:

Чтобы убрать clip-область, можно использовать метод restore. Все те механизмы сохранения/восстановления канвы, что мы рассмотрели в Уроке 146 относятся не только к матрице, но и к clip.
Я в этом уроке использовал объекты Rect. Но у канвы существуют и другие версии метода задания clip-области. Можно использовать RectF, Region и Path.
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
