Para hacer un juego simple, utilicé una plantilla que dibuja un lienzo con mapas de bits como este:
private void doDraw(Canvas canvas) {
for (int i=0;i<8;i++)
for (int j=0;j<9;j++)
for (int k=0;k<7;k++) {
canvas.drawBitmap(mBits[allBits[i][j][k]], i*50 -k*7, j*50 -k*7, null); } }
(El lienzo se define en "run ()" / SurfaceView vive en un GameThread).
Mi primera pregunta es ¿cómo borro (o redibujo) todo el lienzo para un nuevo diseño?
En segundo lugar, ¿cómo puedo actualizar solo una parte de la pantalla?
// This is the routine that calls "doDraw":
public void run() {
while (mRun) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if (mMode == STATE_RUNNING)
updateGame();
doDraw(c); }
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c); } } } }
fuente
mSurfaceHolder.unlockCanvasAndPost(c)
y luegoc = mSurfaceHolder.lockCanvas(null)
, entonces el nuevoc
no contiene lo mismo que el anteriorc
. No puede actualizar solo una parte de SurfaceView, que es lo que estaba preguntando el OP, supongo.Canvas
guarda dibujos antiguos.Dibujar color transparente con el modo claro de PorterDuff hace el truco para lo que quería.
fuente
Bitmap#eraseColor(Color.TRANSPARENT)
, como en la respuesta de HeMac a continuación.Color.TRANSPARENT
es innecesario.PorterDuff.Mode.CLEAR
es totalmente suficiente para unARGB_8888
mapa de bits, lo que significa establecer el alfa y el color en [0, 0]. Otra forma es usarColor.TRANSPARENT
conPorterDuff.Mode.SRC
.Encontré esto en los grupos de Google y esto funcionó para mí.
Esto elimina los dibujos, rectángulos, etc. mientras se mantiene el mapa de bits establecido.
fuente
utilizar el método de reinicio de la clase Path
fuente
Probé la respuesta de @mobistry:
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
Pero no funcionó para mí.
La solución, para mí, fue:
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
Quizás alguien tenga el mismo problema.
fuente
fuente
pegue el código debajo en el constructor de clase de extensión de surfaceview .............
codificación del constructor
codificación xml
prueba el código anterior ...
fuente
Aquí está el código de un ejemplo mínimo que muestra que siempre debe volver a dibujar cada píxel del lienzo en cada cuadro.
Esta actividad dibuja un nuevo mapa de bits cada segundo en SurfaceView, sin borrar la pantalla antes. Si lo prueba, verá que el mapa de bits no siempre se escribe en el mismo búfer y la pantalla alternará entre los dos búferes.
Lo probé en mi teléfono (Nexus S, Android 2.3.3) y en el emulador (Android 2.2).
fuente
SurfaceHolder.Callback
, no soloCallback
.Canvas
si queremos volver a dibujar completamente toda la pantalla. Eso hace que mi afirmación sobre los "dibujos anteriores" sea cierta. ElCanvas
mantiene dibujos anteriores.Canvas
conserva los dibujos anteriores. Pero esto es completamente inútil, el problema es que cuando usaslockCanvas()
usas no sabes cuáles son esos “dibujos anteriores”, y no puedes asumir nada sobre ellos. Quizás si hay dos actividades con un SurfaceView del mismo tamaño, compartirán el mismo Canvas. Tal vez obtenga una parte de la RAM no inicializada con bytes aleatorios. Quizás que siempre esté escrito el logo de Google en el Canvas. No puedes saberlo. Cualquier aplicación que no dibuje cada píxel despuéslockCanvas(null)
está rota.Para mí, llamar
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
o algo similar solo funcionaría después de tocar la pantalla. Entonces, llamaría a la línea de código anterior, pero la pantalla solo se borraría después de tocar la pantalla. Entonces, lo que funcionó para mí fue llamarinvalidate()
seguido de loinit()
que se llama en el momento de la creación para inicializar la vista.fuente
fuente
Borrar en Canvas en java android es similar al borrar HTML Canvas a través de javascript con globalCompositeOperation. La lógica era similar.
U elegirá la lógica DST_OUT (salida de destino).
Nota: DST_OUT es más útil porque puede borrar un 50% si el color de la pintura tiene un 50% de alfa. Entonces, para aclarar completamente a transparente, el alfa de color debe ser 100%. Se recomienda aplicar paint.setColor (Color.WHITE). Y asegúrese de que el formato de la imagen del lienzo sea RGBA_8888.
Después de borrar, vuelva al dibujo normal con SRC_OVER (Source Over).
Actualizar la pantalla de área pequeña literalmente necesitará acceder al hardware gráfico, y tal vez no sea compatible.
Lo más cercano para un mayor rendimiento es el uso de capas de imágenes múltiples.
fuente
No olvide llamar a invalidate ();
fuente
invalidate
después de dibujar algo?Intente eliminar la vista en onPause () de una actividad y agregue onRestart ()
LayoutYouAddedYourView.addView (YourCustomView); LayoutYouAddedYourView.removeView (YourCustomView);
En el momento en que agregue su vista, se llamará al método onDraw ().
YourCustomView, es una clase que amplía la clase View.
fuente
En mi caso, dibujo mi lienzo en un diseño lineal. Para limpiar y volver a dibujar:
y luego, llamo a la clase con los nuevos valores:
Esta es la clase Lienzo:
fuente
Con el siguiente enfoque, puede borrar todo el lienzo o solo una parte.
No olvide deshabilitar la aceleración de hardware, ya que PorterDuff.Mode.CLEAR no funciona con la aceleración de hardware y, finalmente, llama
setWillNotDraw(false)
porque anulamos elonDraw
método.fuente
LAYER_TYPE_HARDWARE
aLAYER_TYPE_SOFTWARE
Su primer requisito, cómo borrar o volver a dibujar todo el lienzo - Respuesta - use el método canvas.drawColor (color.Black) para limpiar la pantalla con un color negro o lo que especifique.
Su segundo requisito, cómo actualizar parte de la pantalla - Respuesta - por ejemplo, si desea mantener todas las demás cosas sin cambios en la pantalla pero en un área pequeña de la pantalla para mostrar un número entero (digamos contador) que aumenta después de cada cinco segundos. luego use el método canvas.drawrect para dibujar esa pequeña área especificando la parte superior derecha inferior izquierda y pintar. luego calcule el valor de su contador (usando postdalayed durante 5 segundos, etc., como Handler.postDelayed (Runnable_Object, 5000);), conviértalo en una cadena de texto, calcule las coordenadas xey en este pequeño rect y use la vista de texto para mostrar el cambio valor del contador.
fuente
Tuve que usar un pase de dibujo separado para limpiar el lienzo (bloquear, dibujar y desbloquear):
fuente
Solo llama
canvas.drawColor (Color.TRANSPARENT)
fuente
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
. Si no me equivoco, el color puede ser cualquier cosa (no tiene por qué ser TRANSPARENTE) porquePorterDuff.Mode.CLEAR
simplemente borrará el clip actual (como hacer un agujero en el lienzo).