2012-12-02 14 views
16

Próbuję przypiąć operację rysowania płótna do klina w kształcie łuku. Jednak nie otrzymuję zamierzonego wyniku po ustawieniu ścieżki przycinającej na płótnie.Canvas.clipPath (Path) nie obcinanie zgodnie z oczekiwaniami

Dla ilustracji, tutaj jest to, co robię:

enter image description here

path.reset(); 

//Move to point #1 
path.moveTo(rect.centerX(), rect.centerY()); 

//Per the documentation, this will draw a connecting line from the current 
//position to the starting position of the arc (at 0 degrees), add the arc 
//and my current position now lies at #2. 
path.arcTo(rect, 0, -30); 

//This should then close the path, finishing back at the center point (#3) 
path.close(); 

To działa, a kiedy po prostu narysować tę ścieżkę (canvas.drawPath(path, paint)) czerpie klina, jak pokazano powyżej. Jednak, kiedy ustawić tę ścieżkę jako ścieżkę obcinania płótna i wyciągnąć do niego:

//I've tried it with and without the Region.Op parameter 
canvas.clipPath(path, Region.Op.REPLACE); 
canvas.drawColor(Color.BLUE); 

pojawia się następujący wynik zamiast (klin pozostałego po prostu pokazać odniesienia):

enter image description here

Zamiast tego wydaje się, że przycina do prostokąta ograniczającego Path, a nie samego Path. Jakieś pomysły, co się tutaj dzieje?

EDYTOWANIE Tak jak aktualizacja, znalazłem o wiele bardziej efektywny sposób na zrobienie tego, co pozwala na przyspieszenie sprzętowe. Najpierw narysuj cały obraz (który chcesz przyciąć) w bitmapie poza ekranem. Zrób BitmapShader użyciu tego Bitmap, ustaw ten shader do Paint, a następnie narysować ścieżkę za pomocą klina że Paint obiektu:

drawMyBitmap(bitmap); 
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
paint.setShader(shader); 

@Override 
public void onDraw(Canvas canvas) { 
    canvas.drawArc(rect,   //The rectangle bounding the circle 
        startAngle, //The angle (CW from 3 o'clock) to start 
        sweepAngle, //The angle (CW from 3 o'clock) of the arc 
        true,   //Boolean of whether to draw a filled arc (wedge) 
        paint   //The paint with the shader attached 
    ); 
} 
+1

Używasz HC lub powyżej lub w inny sposób przy użyciu przyspieszenia sprzętowego? http://developer.android.com/guide/topics/graphics/hardware-accel.html. Jeśli tak, polecenie clipPath nie jest obsługiwane i problematyczne. – Simon

+1

@Simon: O mój boże. Heh. Niestety w tym tygodniu bardzo często odwoływałem się do tego dokumentu, ale całkowicie to przeoczyłem. Wyłączenie HW Accel działało idealnie! Jeśli napiszesz to jako odpowiedź, zaakceptuję to. Jesteś ratownikiem! – kcoppock

+0

Cieszę się, że pomogłem. Powodzenia. – Simon

Odpowiedz

9

Używasz HC lub powyżej lub w inny sposób za pomocą akceleracji sprzętowej?

Jeśli tak, ścieżka przycinania jest nieobsługiwana i problematyczna.

developer.android.com/guide/topics/graphics/hardware-accel.html.

+1

To był problem. :) Przeniesiono część obcinania operacji rysowania na mapę bitmową poza ekranem, a następnie narysowano ją z powrotem na akcelerowanym płótnie HW i działa jak urok! Dzięki jeszcze raz! – kcoppock

+1

@kcoppock To brzmi trochę wstecz. Dlaczego po prostu nie konwertujesz typu warstwy widoku na oprogramowanie i nadal robisz rysunek w 'onDraw()'? –

+0

@ RichardJ.RossIII To miałoby więcej sensu.:) Byłem trochę obcy w tym czasie. Edytowałem w nowy sposób, że teraz radzę sobie z tym problemem, dziękuję za wkład! – kcoppock

2

Pytanie OP w szczególności dotyczy wykorzystania regionu obcinania i zostało odebrane przez @Simona. Należy pamiętać jednak, że istnieje bardziej bezpośredni sposób rysowania wypełnionego łuku:

Tworzenie Paint:

mPaint = new Paint(); 
mPaint.setColor(Color.BLUE); 
mPaint.setStyle(Style.FILL); 
mPaint.setAntiAlias(true); 

Podczas rysowania, wystarczy narysować ścieżkę:

canvas.drawPath(path, mPaint); 
Powiązane problemy