Android更改canvas背景颜色,而不会丢失任何图纸

我试图find一种方法来设置canvas的背景,从自定义颜色select器拾取的颜色,而不删除任何图纸。 我试图创build一个可以在canvas上绘制的应用程序,并将其保存为PNG。 但是当我为当前的canvas设置一个新的背景时,所有的图画都消失了。 我正在使用这样的东西:

mCanvas.drawColor(picker.getColor());

任何想法如何让事情工作?

Solutions Collecting From Web of "Android更改canvas背景颜色,而不会丢失任何图纸"

已经给你的问题的答案都指向了正确的方向:你需要分开你的背景颜色块和前景绘图在不同的层次,然后合并它们,然后将其保存在一个.png文件中。 这也是Adobe Photoshop工作stream的devise方式……如果我们考虑这个问题的话,这是有道理的:例如像MsPaint这样的软件:因为它不使用图层,它必须依赖像floodfillalgorithm完成(虽然以不完整的方式)远程类似于背景变化的东西…

实现这种事情的一种方法是实例化由2个不同的位图支持的2个canvas对象。 第一个Canvas-Bitmap对将在前景中用于绘图,第二个Canvas-Bitmap对将用于合并图层(即前景绘图+背景色块)。 然后第二个位图是什么将保存到.png文件,当你需要保存。 这样,我们的第一个Canvas-Bitmap对存储你的前景信息,如果需要做背景颜色变化,这个信息不会被破坏。 每次进行操作时,图层都可以合并到第二个Canvas-Bitmap对中,这样就可以随时保存正确内容的Bitmap。

这是我为了清除这个方法而创build的一个自定义视图。 它实现了一个简单的视图,使用手指在触摸屏上画一条蓝线,根据所述手指的XY位置改变背景颜色,以便展示背景颜色变化,而不需要完整的实现所固有的不必要的代码复杂性与色轮/菜单/ 除其他外

 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); } } 

为了testing这个视图,这里是一个使用PaintView类的testingActivity。 这两个文件在Android项目中都是自给自足的,因此您可以在真实的设备上进行testing,而无需麻烦:

 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); } } 

当您绘制颜色时,将绘制在您的图纸上。 你需要绘制颜色,然后再绘制其他的东西。

看看如果你想在canvas上改变,那么你必须调用invalidate来应用这些更改你的screen.And如果你调用invalidate然后你的onDraw()方法将调用。

如果你想从颜色select器只改变canvas的背景颜色,然后将颜色值保存在variables中,并保存variables后立即调用invalidate。现在你的onDraw()将调用。现在通过调用onDraw() setBackgroundColor(color variable)中的setBackgroundColor(color variable) onDraw()并画出你想要的一切

使用canvas.drawARGB(a,r,g,b),它将起作用

只要你的背景是和将会是另一种颜色,你可以做:

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

或者,您可以在屏幕外位图上绘制内容,然后将背景和屏幕外的图像绘制到实际的位图上。 这样,您可以更改将在下一个两步绘图发生时使用的背景颜色。

@ Android-Droid

这两行代码对我来说很有魅力。 当用户点击任何颜色(例如:红色)时,将该颜色设置为mPaint

  mPaint.setColor(Color.RED); 

当你想改变canvas颜色

  dv.setBackgroundColor(mPaint.getColor()); 

其中dv是扩展视图的类的对象(自定义视图)。 试试看,如果你遇到任何问题,请告诉我。

也许这是一个古老的问题,但我想为这个解决scheme作出贡献,如果你从一个源代码获取位图,然后用canvas绘制一个drawable,也许这可以适合你:

 @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; } 

希望能帮助到你…