Что является лучшей альтернативой для canvas.clipRect с Region.Op.REPLACE?

Фон

Я работаю над библиотекой, в которой много рисунков на холсте вместо нескольких видов (доступно здесь).

Эта проблема

Работая над тем, чтобы улучшить его и сделать так, чтобы оно соответствовало нашим потребностям приложения (требуется некоторая настройка), я заметил, что некоторые строки помечены как устаревшие:

canvas.clipRect(0f, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, height.toFloat(), Region.Op.REPLACE)

Дело в том, что я не думаю, что есть хороший кандидат для замены этой строки кода более новыми API

Что я нашел

Глядя на документы, вот что написано:

Этот метод устарел на уровне API 26. Значения Region.Op, кроме INTERSECT и DIFFERENCE, могут расширять клип. API обрезки холста предназначены для расширения клипа только в результате операции восстановления. Это позволяет родителю представления обрезать холст, чтобы четко определить максимальную область рисования его дочерних элементов. Рекомендуемые альтернативные вызовы: clipRect(RectF) и clipOutRect(RectF);

Поэтому я попытался использовать любую из этих функций, но обе они вызвали проблемы с чертежом, как это было раньше.

Глядя на устаревание, кажется, что сама функция помечена, но не Region.Op.REPLACE:

Так что, возможно, у него нет альтернативы...

Вопросы

  1. Какова лучшая альтернатива в этом случае?
  2. Почему именно это устарело?
  3. В отличие от некоторых устаревших функций, я предполагаю, что эта функция должна быть безопасной для использования в случае, если я не могу найти альтернативу, верно?

1 ответ

Решение

1: Все методы, которые используют пользовательские Region.Op устарели, поэтому теперь можно использовать только два варианта метода: clipRect / clipPath (который представляет Region.Op.INTERSECT) а также clipOutRect / clipOutPath (который представляет Region.Op.DIFFERENCE). Для достижения функции, аналогичной Region.Op.REPLACE надо использовать save() а также restore() методы:

canvas.save();        // IMPORTANT: save current state of clip and matrix (i.e. unclipped state) (let's say it's state #1)
canvas.clipRect(0, 0, 100, 100); // do some clipping
canvas.drawLine(...); // do some clipped drawing
canvas.restore();     // IMPORTANT: get back to previously saved (unclipped) state of the canvas (restores state #1)

canvas.save(); // now save again the current state of canvas (clip and matrix) (it's state #2)
canvas.clipRect(200, 200, 400, 400); // now we can do some other clipping (as we would do with Region.Op.REPLACE before)
canvas.drawLine(...); // and some other drawing
canvas.restore(); // get back go previously saved state (to state #2)

Примечание. Canvas внутренне использует стек, поэтому вы можете даже save() несколько раз в разные моменты. Вы просто не можете позвонить canvas.restore() больше раз, чем canvas.save() назывался.

Также важно отметить, что призыв к canvas.restore() изменяет прямоугольник клипа (на то же значение, которое было, когда canvas.save() назывался). Таким образом, вы должны тщательно разместить restore() Вызовите после всех методов рисования, которые требуют применения отсечения.

2: Возможно из-за некоторых оптимизаций производительности. Мне кажется, я где-то читал (сейчас не смог найти), что для аппаратного ускорения на графическом процессоре они могут использовать только операции клипа INTERSECT / DIFFERENCE, а другие должны отступать от обработки ЦП. Это может быть причиной.

РЕДАКТИРОВАТЬ: Вот некоторый связанный ответ, что, поскольку ICS с включенным ускорением HW, некоторые операции ClipRect не поддерживаются.

3: как говорится в документации, он перестанет работать в Android P (возможно, только при таргетинге на Android P):

На уровне API Уровень API Build.VERSION_CODES.P только INTERSECT и DIFFERENCE являются допустимыми параметрами Region.Op.

Другие вопросы по тегам