Android cambia el color de fondo del lienzo sin perder ningún dibujo de él

Estoy tratando de encontrar una manera de establecer el fondo del lienzo con un color recogido de selector de color personalizado sin quitar ningún dibujo sobre él. Estoy tratando de crear una aplicación que puede dibujar sobre lienzo y guardarlo como png. Pero cuando pongo un nuevo fondo en el lienzo actual, todos los dibujos se han ido. Estoy usando algo como esto:

mCanvas.drawColor(picker.getColor());

¿Alguna idea de cómo puedo hacer que las cosas funcionen?

Las respuestas ya dadas a su pregunta están todas apuntando en la dirección correcta: usted necesita separar su bloque de color de fondo y su dibujo de primer plano en capas separadas, luego fusionarlos antes de guardar todo en un archivo .png. Esto es lo que el flujo de trabajo de Adobe Photoshop está diseñado también … Tiene sentido, si lo pensamos: tomar por ejemplo un software como MsPaint: porque no utiliza capas, tiene que depender de cosas como algoritmos floodfill para Lograr (aunque de manera incompleta) algo remotamente similar a un cambio de fondo …

Una forma de implementar tal cosa sería instanciar 2 objetos Canvas respaldados por 2 mapas de bits diferentes. El primer par de Canvas-Bitmap se usaría para el dibujo en el primer plano y el segundo par de Canvas-Bitmap se usaría para el dibujo de capas combinadas (es decir, dibujo de primer plano + bloque de color de fondo). Entonces el segundo mapa de bits es lo que se guardará en un archivo .png cuando necesite que se guarde. De esta manera, nuestro primer par de Canvas-Bitmap almacena su información de primer plano, que no se destruye si es necesario realizar un cambio de color de fondo. Cada vez que se realiza una operación, las capas se pueden combinar en el par de Canvas-Bitmap para que siempre haya un Bitmap con el contenido correcto que esté listo para ser guardado a su antojo.

Esta es una vista personalizada que hice para borrar esta metodología. Implementa una vista simple que se utiliza para pintar una línea azul en la pantalla táctil con un dedo, cambiando el color de fondo dependiendo de la posición XY de dicho dedo para demostrar un cambio de color de fondo sin complejidad de código innecesaria inherente a una implementación completa Con una rueda de color / menús / inter alia :

 package com.epichorns.basicpaint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Paint.Style; import android.view.View; public class PaintView extends View{ Bitmap mMergedLayersBitmap=null; //Note: this bitmap here contains the whole of the drawing (background+foreground) to be saved. Canvas mMergedLayersCanvas=null; Bitmap mBitmap = null; //bitmap onto which we draw our stuff Canvas mCanvas = null; //Main canvas. Will be linked to a .bmp file int mBackgroundColor = 0xFF000000; //default background color Paint mDefaultPaint = new Paint(); Paint mDrawPaint = new Paint(); //used for painting example foreground stuff... We draw line segments. Point mDrawCoor = new Point(); //used to store last location on our PaintView that was finger-touched //Constructor: we instantiate 2 Canvas-Bitmap pairs public PaintView(Context context, int width, int height) { super(context); mMergedLayersBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mMergedLayersCanvas = new Canvas(mMergedLayersBitmap); mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } //Change background color public void changeColor(int newColor){ mBackgroundColor = newColor; invalidate(); //refresh view: this will indirectly invoke onDraw soon afterwards } //Called by user of PaintView in order to start a painting "stroke" (finger touching touch-screen): stores the //location of the finger when it first touched the screen public void startDraw(int x, int y, int radius, int color){ mDrawPaint.setColor(color); mDrawPaint.setStyle(Style.STROKE); mDrawPaint.setStrokeWidth(radius); mDrawCoor.x = x; mDrawCoor.y = y; } //Called by user of PaintView when finger touching touch-screen is moving (must be called after a startDraw, //as the latter initializes a couple of necessary things) public void continueDraw(int x, int y){ mCanvas.drawLine(mDrawCoor.x, mDrawCoor.y, x, y, mDrawPaint); mDrawCoor.x = x; mDrawCoor.y = y; invalidate(); //refresh view: this will indirectly invoke onDraw soon afterwards } //Merge the foreground Canvas-Bitmap with a solid background color, then stores this in the 2nd Canvas-Bitmap pair. private void mergeLayers(){ mMergedLayersCanvas.drawColor(mBackgroundColor); mMergedLayersCanvas.drawBitmap(mBitmap, 0, 0, mDefaultPaint); } @Override public void onDraw(Canvas canvas){ mergeLayers(); canvas.drawBitmap(mMergedLayersBitmap, 0, 0, mDefaultPaint); } } 

Para probar esta vista, aquí está una actividad de prueba que usa la clase de PaintView . Ambos archivos son autosuficientes en un proyecto de Android, por lo que puede probarlo en su dispositivo real sin problemas:

 package com.epichorns.basicpaint; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import com.epichorns.basicpaint.PaintView; public class BasicPaintActivity extends Activity { PaintView mPaintView=null; LinearLayout mL = null; boolean mIsDrawing=false; int mBackgroundColor = 0xFF000000; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Display display = getWindowManager().getDefaultDisplay(); final float dispWidth = (float)display.getWidth(); final float dispHeight = (float)display.getHeight(); mPaintView = new PaintView(this, display.getWidth(), display.getHeight()); mPaintView.changeColor(mBackgroundColor); mPaintView.setOnTouchListener(new View.OnTouchListener(){ public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_DOWN){ mPaintView.startDraw((int)event.getX(), (int)event.getY(), 6, 0x806060FF); mIsDrawing=true; return true; } else if(event.getAction()==MotionEvent.ACTION_UP){ mIsDrawing=false; return true; } else if(event.getAction()==MotionEvent.ACTION_MOVE){ if(mIsDrawing){ //To demonstrate background change, change background color depending on XY position int r = (int)(255f*event.getX()/dispWidth); int g = (int)(255f*event.getY()/dispHeight); mBackgroundColor = Color.argb(0xFF, r,g, 0x00); Log.d("DEBUG1", "Color channels: (r, g) = ("+String.valueOf(r)+", "+String.valueOf(g)+")"); mPaintView.changeColor(mBackgroundColor); //now, draw stuff where finger was dragging... mPaintView.continueDraw((int)event.getX(), (int)event.getY()); return true; } else{ return false; } } return false; } }); setContentView(mPaintView); } } 

Cuando dibujas el color, se dibuja sobre tus dibujos. Tienes que dibujar el color, y luego dibujar todo lo demás de nuevo.

Mira si quieres cambiar en el lienzo, entonces usted tiene que llamar a invalidar para aplicar estos cambios a su pantalla. Y si llama invalidar entonces su método onDraw() llamará.

Si desea cambiar sólo el color de fondo del lienzo del selector de color a continuación, guarde el valor del color en la variable y la llamada invalidar justo después de guardar la variable. onDraw() su onDraw() llamará. Ahora cambie el fondo del lienzo llamando setBackgroundColor(color variable) en onDraw() Y dibujar todo lo que quieras

Mientras su fondo sea y esté en otro color, usted puede hacer:

 for (x...) for (y...) if (bitmap.getPixel(x,y) == oldBackgroundColor) bitmap.setPixel(x,y,newBackgroundColor) 

O bien, puede dibujar su contenido en un mapa de bits fuera de pantalla y dibujar el fondo y, a continuación, la offscreen en el mapa de bits real. De esta forma, puede cambiar el color de fondo que se utilizará cuando suceda el siguiente dibujo de dos pasos.

Use canvas.drawARGB (a, r, g, b) y funcionará para definite

@ Android-Droid

Estas dos líneas de código funcionaron como encanto para mí. Cuando el usuario hace clic en cualquier color (por ejemplo: Rojo), coloque ese color en mPaint como

  mPaint.setColor(Color.RED); 

Y cuando usted desea cambiar nunca el color de la lona

  dv.setBackgroundColor(mPaint.getColor()); 

Donde dv es el objeto de la clase que extiende la vista (Vista personalizada). Pruébalo y házmelo saber si te enfrentas a cualquier problema.

Tal vez es una vieja pregunta, pero quiero contribuir con esta solución, En caso de que usted está tomando el mapa de bits de una fuente, y luego hacer un dibujable con lienzo, tal vez esto puede caber u:

 @Override public Bitmap transform(final Bitmap source) { //Background for transparent images Bitmap backg = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); backg.eraseColor(Color.WHITE); // Any color you want... Paint back = new Paint(); BitmapShader backshader = new BitmapShader(backg, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); back.setShader(backshader); back.setAntiAlias(true); // Image for the draw final Paint paint = new Paint(); paint.setAntiAlias(true); paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig()); Canvas canvas = new Canvas(output); // IMPORTANT THING canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, back); // Draw the background first... canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint); // And then Draw the image, so it draws on top of the background if (source != output) { source.recycle(); } // This is for if i want to put a border in the drawable, its optional Paint paint1 = new Paint(); paint1.setColor(Color.parseColor("#CC6C7B8B")); paint1.setStyle(Style.STROKE); paint1.setAntiAlias(true); paint1.setStrokeWidth(2); canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint1); // and then, return the final drawable... return output; } 

Espero eso ayude…

  • Dibujando una vista y todos sus hijos
  • Animación de juegos 2D android
  • Cómo rotar TextView sin recortar sus límites?
  • Dibuja un círculo con bordes lisos
  • Cómo obtener un soundcloud como formas de onda en Android
  • Android - Cómo superponer un camino encima de otro
  • Cómo utilizar matrix.preScale (x, y)
  • Cómo desenfocar una parte de la imagen en Android?
  • Mal rendimiento de Android Canvas.drawBitmap - cambiar a OpenGL?
  • ¿Cómo puedo dibujar una vista animada en android?
  • Rasca la pantalla para mostrar una imagen en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.