Canvas.drawArc () artefactos
Dibujo un arco sobre lienzo en una vista personalizada como se muestra a continuación. Paint
y el rectangle
se definen fuera de onDraw()
y se añaden allí con fines de simplicidad.
protected void onDraw(Canvas canvas) { super.onDraw(canvas); RectF rectangle = new RectF(60f, 60f, 480f, 480f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0x40000000); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(120); canvas.drawArc(rectangle, 225f, 315f, false, paint); }
Cuando ejecuto este código en Galaxy Nexus con 4.3, hay siguientes artefactos.
- No se encontró ningún recurso que coincida con el nombre dado '@ style / Widget.RatingBar.Small'
- ¿Necesito volver a llamar a super.onDraw () en una vista personalizada?
- Visor dinámico de altura
- Cómo usar una misma fontface personalizada para toda la vista en android?
- Dos barras de acción (abajo y arriba) al mismo tiempo?
No hay tales artefactos cuando se ejecuta en Nexus 5 con 4.4.4 sin embargo.
Observé tales artefactos por ángulos como (225f, 315f) y algunos otros ángulos solamente. La mayor parte del tiempo el arco tiene una forma correcta.
¿Hay alguna manera de evitar esos artefactos?
Actualización: He intentado usar software, hardware y ninguna capa usando setLayerType()
. Los artefactos cambiaron su forma, pero todavía estaban presentes.
- Vista circular personalizada
- ImageViews son invisibles si el método dispatchDraw de Viewgroups se sobrescribe en android
- Cómo utilizar Path (android.graphics.Path) con lienzo en android?
- SherlockActionBar: Cómo ajustar CustomView contra actionBar
- Deslizar / arrastrar la vista de Android desde la parte inferior de la pantalla
- ¿El editor de diseño de Android Studio muestra propiedades de vista personalizada?
- Pantalla personalizada con líneas de puntos
- Rectángulo efecto de rizo sin límites
Soy un novato StackOverflow, quería añadir un comentario pero no podía (tener puntos insuficientes) así que tuve que poner mi comentario en una respuesta!
Una cosa extraña es que el arco sobrepasa la posición final especificada con una línea vertical recta en el lado exterior. El punto final interno parece estar bien. Por supuesto esto y el otro desorden de líneas no dice qué causa el problema.
Parece que aparece cuando el ángulo final es exactamente un múltiplo de 90 grados. Esto se parece a un error de cálculo numérico, un problema de redondeo de flotación, etc. @kcoppock comentó que 314.98f ya elude el error. Probablemente cualquier valor que no sea exactamente 315.0f puede hacer el truco.
Si la optimización del código está involucrada (intenta dibujar el arco en segmentos de línea lo más pequeños posible) otro truco que puede funcionar es simplificar el arco cortándolo en pedazos -> utilizar varias llamadas drawArc que cada uno abarcan un determinado ángulo máximo. Los candidatos son 30, 45, 90 y 180 grados. Queda por verse si las articulaciones serán invisibles …
Es un poco un tiro largo, espero que cualquiera de estas sugerencias podría funcionar.
¡He encontrado la solución! 🙂
En lugar de esto:
RectF rectangle = new RectF(60f, 60f, 480f, 480f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0x40000000); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(120); canvas.drawArc(rectangle, 225f, 315f, false, paint);
Utilizar esta:
RectF rectangle = new RectF(60f, 60f, 480f, 480f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0x40000000); paint.setStyle(Paint.Style.FILL); float strokeWidth = 120; float startAngle = 225f; float sweepAngle = 315f; RectF pathRect = new RectF(); Path path = new Path(); float s = strokeWidth / 2; pathRect.left = rectangle.left - s; pathRect.right = rectangle.right + s; pathRect.top = rectangle.top - s; pathRect.bottom = rectangle.bottom + s; path.arcTo(pathRect, startAngle, sweepAngle); pathRect.left = rectangle.left + s; pathRect.right = rectangle.right - s; pathRect.top = rectangle.top + s; pathRect.bottom = rectangle.bottom - s; path.arcTo(pathRect, startAngle + sweepAngle, -sweepAngle); path.close(); canvas.drawPath(path, paint);
Este código produce una ejecución más lenta, pero no produce artefactos. 🙂
- Android: genera una intención simulada y devuelve algunos datos de intenciones
- Google Analytcs seguimiento mejorado de comercio electrónico para Android cuestión