Die Antworten auf Ihre Frage weisen alle in die richtige Richtung: Sie müssen Ihren Hintergrundfarbblock und Ihre Vordergrundzeichnung in separaten Ebenen trennen und dann zusammenführen, bevor Sie die gesamte Datei in einer PNG-Datei speichern . So gestaltet sich auch der Adobe Photoshop Workflow ... Wenn wir darüber nachdenken, ergibt das Sinn: Nehmen wir zum Beispiel eine Software wie MsPaint: Da sie keine Ebenen verwendet, muss sie sich auf Dinge wie Floodfill-Algorithmen verlassen erreichen (wenn auch auf eine unvollständige Weise) etwas entfernt ähnlich wie eine Hintergrundänderung ...
Eine Möglichkeit, so etwas zu implementieren wäre, 2 Canvas-Objekte zu instanziieren, die von 2 verschiedenen Bitmaps unterstützt werden. Das erste Canvas-Bitmap-Paar wird für Ihre Zeichnung im Vordergrund verwendet, und das zweite Canvas-Bitmap-Paar wird für die Zeichnung mit verbundenen Layern verwendet (d. H. Vordergrundzeichnung + Hintergrundfarbblock). Dann wird das 2. Bitmap in einer .png-Datei gespeichert, wenn Sie es zum Speichern benötigen. Auf diese Weise speichert unser erstes Canvas-Bitmap-Paar Ihre Vordergrundinformationen, die nicht zerstört werden, wenn eine Hintergrundfarbe geändert werden muss. Jedes Mal, wenn eine Operation ausgeführt wird, können die Layer in das zweite Canvas-Bitmap-Paar zusammengeführt werden, sodass immer ein Bitmap mit dem richtigen Inhalt vorhanden ist, der nach Belieben gespeichert werden kann.
Hier ist eine benutzerdefinierte Ansicht, die ich gemacht habe, um diese Methodik zu klären. Es implementiert eine einfache Ansicht, die verwendet wird, um eine blaue Linie auf dem Berührungsbildschirm unter Verwendung eines Fingers zu malen, wobei sich eine Hintergrundfarbe abhängig von der XY-Position des Fingers ändert, um eine Hintergrundfarbänderung ohne unnötige Codekomplexität einer vollständigen Implementierung zu demonstrieren mit einem Farbrad/menus/unter anderem:
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);
}
}
um diese Ansicht zu testen, hier ist ein Test, der die Aktivität PaintView
-Klasse verwendet. Diese beiden Dateien sind autarke in einem Android-Projekt, so dass Sie es auf Ihrem realen Gerät ohne großen Aufwand testen:
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 X-Y 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);
}
}
Sie müssen uns die OnDraw-Methode zeigen .. – Ronnie
Hallo, ich habe eine Lösung Implementierung unten angehängt. Es tut ziemlich genau das, was Sie wollen, wie es in Ihrer Frage beschrieben ist. – epichorns