Что является лучшей альтернативой для 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 ответ
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.