Подтвердить что ты не робот

На Android, как я могу сделать странные области отсечения?

Вот как создать область обрезки по форме круга:

Path path = new Path();
path.addCircle(200,200,100,Direction.CW);
c.clipPath(path); // c is a Canvas

Теперь на холсте есть область отсечения, которая предотвращает рисование чего-либо за пределами этого круга. Но, если я хочу, чтобы область отсечения была сформирована как пончик (или что-то еще)?

Я попытался сыграть с созданием второго Пути и использовать toggleInverseFillType на нем, а затем добавить это к исходному пути, но это, похоже, не работает.

В качестве альтернативы вместо использования Path можно просто создать Bitmap для использования в качестве маски и как-то установить его как обтравочную маску на Canvas?

EDIT: Ответ - это то, что мне нужно с одним небольшим дополнением. При выполнении нескольких операций на холсте всегда используйте Op.REPLACE при первом вызове clipPath. Это заменит любой существующий клиппат на этом холсте.

Для справки, вот что я обнаружил, что означают 6 разных значений Region.Op. Представьте себе диаграмму Венна с двумя кругами. "B" - это та часть, где два круга перекрываются. "A" - это неперекрывающийся левый круг. "C" - неперекрывающийся правый круг.

c.clipPath(a,Region.Op.REPLACE);
c.clipPath(b,???);

Region.Op.DIFFERENCE         -> A..            
Region.Op.INTERSECT          -> .B.            
Region.Op.REPLACE            -> .BC            
Region.Op.REVERSE_DIFFERENCE -> ..C            
Region.Op.UNION              -> ABC
Region.Op.XOR                -> A.C

"." указывает часть, которая не нарисована. Извините, если это не особенно понятно. Трудно хорошо описывать без графики.

4b9b3361

Ответ 1

Из Canvas javadoc:

Canvas#clipPath(Path path, Region.Op op) - Изменить текущий клип с указанным путем.

Итак, для примера вашего пончика:

  • Создайте 2 пути. Один для большего круга, один для меньшего круга.
  • Canvas#clipPath( Path ) с большим кругом Path.
  • Вызовите метод Canvas#clipPath( Path, Region.Op ) на вашем холсте с меньшим кругом Path для первого аргумента и соответствующим Region.Op значение enum для второго аргумента.

    Path largePath = new Path();
    largePath.addCircle(200,200,100,Direction.CW);
    Path smallPath = new Path();
    smallPath.addCircle(200,200,40,Direction.CW);
    c.clipPath(largePath); // c is a Canvas
    c.clipPath(smallPath, Region.Op.DIFFERENCE);
    

Снова измените значение Region.Op enum, чтобы получить разные эффекты...