Android change canvas background color without losing any drawings from it

后端 未结 3 1748
暗喜
暗喜 2021-02-09 02:22

I\'m trying to find a way to set background of canvas with a color picked up from custom color picker without removing any drawings on it. I\'m trying to create an application w

相关标签:
3条回答
  • 2021-02-09 02:29

    The answers already given to your question are all pointing in the right direction: you do need to separate your background color block and your foreground drawing in separate layers, then merge them before saving the whole of it in a .png file. This is how Adobe Photoshop workflow is designed as well... It does make sense, if we think about it: take for example a software like MsPaint: because it doesn't use layers, it has to rely on stuff like floodfill algorithms to accomplish (albeit in an incomplete way) something remotely similar to a background change...

    One way to implement such a thing would be to instantiate 2 Canvas objects backed by 2 different bitmaps. The first Canvas-Bitmap pair would be used for your drawing at the foreground, and the second Canvas-Bitmap pair would be used for your merged-layers drawing (i.e. foreground drawing + background color block). Then the 2nd Bitmap is what will be saved to a .png file when you need it to be saved. This way, our first Canvas-Bitmap pair stores your foreground info, which is not destroyed if a background color change needs to be made. Everytime an operation is made, the layers can be merged into the 2nd Canvas-Bitmap pair so that there is always a Bitmap with the correct content that is ready to be saved at your whim.

    Here is a custom View I made so as to clear this methodology up. It implements a simple view used to paint a blue line on the touch-screen using a finger, with a background color changing depending on the X-Y position of said finger so as to demonstrate a background color change without unnecessary code complexity inherent of a complete implementation with a color wheel/menus/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);
        }
    
    }
    

    In order to test this view, here is a test Activity that uses the PaintView class. Both of those files are self-sufficient in an Android project, so that you can test it on your real device without hassle:

    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);
        }
    
    
    
    
    }
    
    0 讨论(0)
  • 2021-02-09 02:32

    Look if you want to change in canvas then you have to call invalidate to apply these changes your screen.And if you call invalidate then your onDraw() method will call.

    If you want to change just background color of canvas from color picker then save color value in variable and call invalidate just after saving variable.Now your onDraw() will call.Now change background of canvas by calling setBackgroundColor(color variable) in onDraw() and draw everything else you want

    0 讨论(0)
  • 2021-02-09 02:38

    When you draw the color, it's drawn over your drawings. You need to draw the color, and then draw every thing else again.

    0 讨论(0)
提交回复
热议问题