Canvas clipPath работает только на эмуляторе Android

Я пытаюсь использовать canvas.clipPath() для рисования растрового изображения внутри ограничивающего круга, аналогичного действию Clipping в демонстрациях APP. Проблема в том, что мой код правильно отображается только на эмуляторе, при запуске на реальном Samsung Galaxy Nexus 4.2 кажется, что clipPath работает больше как прямоугольное отсечение. Я совсем запутался! Я создаю новый Path() и декодирую растровое изображение в своем окне просмотра. Какие-либо предложения?

@Override
protected void onDraw(Canvas canvas) {
    Point point = getPoint();
    path.reset();
    canvas.clipPath(path); // makes the clip empty
    path.addCircle(point.x, point.y, getScale() * 140, Path.Direction.CCW);
    canvas.clipPath(path, Region.Op.REPLACE);

    Point scaledSize = new Point((int) (bitmapSize.x * getScale()), (int) (bitmapSize.y * getScale()));
    Point topLeft = new Point((point.x - (scaledSize.x / 2)), (point.y - (scaledSize.y / 2)));
    canvas.drawBitmap(bitmap, null, new Rect(topLeft.x, topLeft.y, topLeft.x + scaledSize.x, topLeft.y + scaledSize.y), paint);
}

Galaxy Nexus GalaxyNexus

Эмулятор

Эмулятор


person Cliff    schedule 03.06.2013    source источник


Ответы (3)


clipPath не поддерживается для аппаратного ускорения. Вы можете создать обрезанное растровое изображение, используя что-то вроде этого:

Bitmap clippedBitmap = ... // Create same size bitmap as source
Paint paint = new Paint();
Canvas canvas = new Canvas(clippedBitmap);
paint.setColor(Color.RED);
paint.setStyle(PAint.Style.FILL);
paint.setFilterBitmap(true);
canvas.drawCircle(cx, cy, radius, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));    
canvas.drawBitmap(sourceBitmap, 0, 0, paint);

Сделайте это один раз, а затем нарисуйте обрезанное растровое изображение вместо исходного.

person yoah    schedule 03.06.2013
comment
Идеальный! Это работает как шарм! А что, если я хочу анимировать вырезку, уменьшить/увеличить размер моего круга? Нужно ли мне создавать новые растровые изображения для каждого вырезания или я могу повторно использовать растровое изображение и связанный с ним холст, каждый раз перерисовывая из исходного источника? - person Cliff; 03.06.2013
comment
Вы можете использовать одно растровое изображение, нарисовать внутренний круг меньшего или большего размера, а затем скопировать замаскированную область из исходного растрового изображения в новое растровое изображение. Обрезанное растровое изображение будет иметь меньшую или большую прозрачную область в зависимости от этапа анимации. - person yoah; 04.06.2013

ClipPath не поддерживается для аппаратного ускорения

Вы можете закрыть аппаратное ускорение, используя это:

setLayerType(View.LAYER_TYPE_SOFTWARE, null);
person 8-bit    schedule 09.07.2013
comment
Начиная с какого API это работает хорошо? Я заметил, что его можно не использовать, например, на Android 4.4. - person android developer; 24.02.2016

ClipPath не поддерживает аппаратное ускорение. Проверьте ссылку ниже в разделе Неподдерживаемые операции рисования.

http://developer.android.com/guide/topics/graphics/hardware-accel.html#drawing-support

Вы можете использовать приведенное ниже для справки и изменить параметры круга рисования в соответствии с вашими потребностями.

public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    DrawingView dv = new DrawingView(this);
    dv.setBackgroundColor(Color.RED);
    setContentView(dv);
}

class DrawingView extends View{
Bitmap bitmap;


 public DrawingView(Context context)
 {
 super(context);
 bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.sqaure);   
}


@Override
public void onDraw(Canvas canvas)
{
 Paint paint = new Paint();
 //paint.setStyle(Paint.Style.FILL);
 // paint.setColor(Color.CYAN);
 canvas.drawBitmap(getclip(), 0, 0, paint);//originally x and y is o and o .

 } 
 public Bitmap getclip()
 {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
        bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(),
        bitmap.getHeight());
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
//paint.setColor(color);
canvas.drawCircle(bitmap.getWidth() / 2-40,
        bitmap.getHeight() / 2, bitmap.getWidth() / 2-40, paint);
    // change the parameters accordin to your needs.
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
    }
  } 
}

введите здесь описание изображения

person Raghunandan    schedule 03.06.2013