Canvas 'drawLine y drawRect no incluye la posición final?
Para mi sorpresa, acabo de descubrir que drawLine y drawRect no incluyen la posición final, es decir:
canvas.drawLine(100, 100, 100, 100, paint);
o
- Cómo crear este tipo de pincel para pintar en android
- Android: firma digital con Bezier
- Dibujo sobre lienzo y varios objetos de pintura
- Android - Cómo dibujar en vista
- Android FingerPaint Deshacer / Rehacer la implementación
RectF rect = new RectF(100, 100, 100, 100); canvas.drawRect(rect, paint);
No dibujará nada.
Mi pintura se define como sigue:
Paint paint = new Paint(); paint.setAntiAlias(false); paint.setStyle(Paint.Style.FILL); return paint;
He intentado definir mi pintura como FILL_AND_STROKE, pero no ayudaría.
DrawPaint de Android () javadoc ni siquiera la lista stopX y stopY params!
Por lo tanto, si quiero dibujar una línea vertical que va exactamente desde beginY hasta endY (inclusive), tengo que hacer lo siguiente:
canvas.drawLine(constX, beginY, constX, endY + 1)
Note que no he añadido 1 a la posición final de X, sólo para terminar Y (xstays lo mismo que quiero una línea vertical).
Mi dispositivo es HTC SENSE.
Editar: Simon, tienes razón, en lugar de hacer una pregunta Acabo de tratar de compartir mi sentimiento de sorpresa de que Android no hace lo que sus documentos dicen en un caso tan fundamental como el dibujo básico, y asegúrese de que yo didn ' No hago ningún error estúpido en mi camino.
Para hacerme más claro: javadoc de drawRect dice:
Public void drawRect (flotador a la izquierda, flotador superior, flotante a la derecha, fondo flotante, pintura)
Dibuja el Rect especificado usando la pintura especificada. El rectángulo se rellenará o enmarcará según el estilo de la pintura.
Left – El lado izquierdo del rectángulo a dibujar
Top – La parte superior del rectángulo a dibujar
Derecha – El lado derecho del rectángulo a dibujar
Bottom – La parte inferior del rectángulo a dibujar
Paint – La pintura usada para dibujar el rect
Por lo tanto, al escribir
canvas.drawRect(x1, y1, x2, y2)
Usted espera un rectángulo cuyas esquinas están en (x1, y1); (X _ {1}, y _ {2}); (X2, y1) y (x2, y2).
Android dice: ¡mal! Estarán en (x1, y1); (X _ {1}, y _ {2-1}); (X2-1, y1) y (x2-1, y2-1).
Para los curiosos: poner el recorte de lienzo:
canvas.clipRect(x1, y1, x2, y2)
Luego trate de dibujar un punto:
canvas.drawPoint(x1, y1, paint);
Y usted consigue un punto en la pantalla.
Luego intente en la esquina opuesta:
canvas.drawPoint(x2, y2, paint);
Nada aparece Nada aparecerá en las 2 esquinas restantes:
canvas.drawPoint(x1, y2, paint); canvas.drawPoint(x2, y2, paint);
¿Todavía no te sorprende a la gente?
Así que la conclusión es que Android trata las coordenadas derecha e inferior como exclusivas, lo que significa que al escribir:
canvas.clipRect(x1, y1, x2, y2)
Obtendrá los límites de recorte de (x1, y1, x2 – 1, y2 – 1). Lo mismo ocurre con cada método que toma las coordenadas derecha e inferior o los objetos Rect / RectF .
- Detección de color de la imagen de fondo con Android Paint
- ¿Definir un estilo de pintura, color, etc en XML?
- ¿Cómo aplicar el color del pincel con puntos en la aplicación Paint android?
- Dibujar línea discontinua en Android mediante programación
- ¿Cómo conseguir la altura del texto con el ancho fijo y conseguir la longitud del texto que cabe en un marco?
- Android - paint.setShadowLayer Omitiendo shadowColor
- Cómo convertir rgb color a int en java
- Asegúrese de que el área del mapa de bits sea transparente al tocar
Su pregunta revela una inconsistencia en la API de dibujo de Android. Tu dices
Por lo tanto, si quiero dibujar una línea vertical que va exactamente desde beginY hasta endY (inclusive), tengo que hacer lo siguiente:
canvas.drawLine(constX, beginY, constX, endY + 1)
Note que no he añadido 1 a la posición final de X, sólo para terminar Y (xstays lo mismo que quiero una línea vertical).
La frase entre corchetes es en mi opinión la clave para entender la naturaleza de la inconsistencia:
También podría añadir 1 a la posición final X (o incluso a la posición inicial X!), Y obtendría exactamente la línea idéntica en píxeles. ¿Porqué es eso? Debido a que el algoritmo subyacente para transformar desde el concepto de "píxel izquierdo en / píxeles a la izquierda" de Android -concepto al "píxel de inicio y fin en" -concepto es el siguiente (mostrado sólo para x, para y es lo mismo):
int left, top, right, bottom; // left/top pixel inclusive, right/bottom pixel exclusive int x1, y1, x2, y2; // x1/y1 and x2/y2 pixels inclusive if ( left == right ) { x1 = x2 = left; } else if ( left < right ) { x1 = left; x2 = right - 1; } else { x1 = right; x2 = left - 1; }
El resultado de esto (en mi opinión sub-óptimo) la conversión es que la línea
canvas.drawLine(150, 150, 149, 160, paint);
Es exactamente paralelo a
canvas.drawLine(150, 150, 151, 160, paint);
Creo que todo el mundo espera una especie de V inversa, ya que los puntos finales están separados por al menos 1 píxel (su distancia es de dos píxeles) y los puntos de partida son idénticos.
Pero probado en varios dispositivos y versiones de Android, la 1ª línea perfectamente vertical está en la columna de píxeles 149 y la 2ª en la columna 150.
BTW: La transformación correcta para usar el "inicio y final del píxel en" -concept es:
int x1, y1, x2, y2; // x1/y1 and x2/y2 pixels inclusive if ( x1 <= x2 ) ++x2; else ++x1; if ( y1 <= y2 ) ++y2; else ++y1; canvas.drawLine(x1, y1, x2, y2, paint);
Su pregunta es esencialmente la respuesta para esto . Gracias.
Yo, por una parte, no estoy sorprendido por esto, y no lo querría de otra manera. Este es el por qué:
-
Es consistente con
java.awt
,javax.swing
y otras APIs, así como los métodos Java básicos comoString.substring(int, int)
yList<?>.get(int)
. -
Es compatible con
android.graphics.RectF
, que no se preocupa por píxeles, ¿cómo puede tener una fracción de un píxel? -
El API es conveniente:
-
Para un rectángulo de 40 × 30, instanciar
Rect(0, 0, 40, 30)
-
Rect.right - Rect.left == Rect.width()
-
-
Las matemáticas y la geometría son más fáciles de esta manera. Por ejemplo, si desea dibujar un rectángulo centrado en el lienzo:
Rect clipBounds = canvas.getClipBounds () Int myRectWidth = 20; Int myRectHeight = 10; Int left = (clipBounds.width () - myRectWidth) / 2; Int top = (clipBounds.height () - myRectHeight) / 2; Int right = clipBounds.width () - izquierda; // ¿Ves lo bonito que es esto? Int bottom = clipBounds.height () - arriba; // ¡Esto no funcionaría si el fondo fuera inclusivo! Canvas.drawRect (izquierda, arriba, derecha, abajo);
El API es correcto; La documentación de la API , por desgracia, sólo carece de detalle.
(En realidad, se menciona en el detalle para el Rect.contains(int, int)
. Es lamentable que Google deje que el API salga por la puerta sin que las propias variables de campo estén documentadas.)
Si su fondo es negro, agregue una declaración paint.setColor(Color.RED);
Y también tuviste un pase RectF rect = new RectF(100, 100, 100, 100);
Todos los puntos son iguales, intente RectF rect = new RectF(100, 100, 200, 200);
O para line canvas.drawLine(10, 10, 10, 10 + 15, paint);
Su rect debe trabajar aletas, trate de añadir un poco de fondo, su línea es ahora kust un píxel, el último parámetro dos no es la longitud, es la posision final.
- Android aapt alta utilización del procesador (y lento!)
- ¿Cómo puedo compartir recursos entre los diferentes proyectos de Eclipse, para evitar la duplicación?