简体   繁体   中英

Draw bitmap over already drawn background on SurfaceView

In my SurfaceView when I click on the screen it creates black dots after that I connect them and it has a filled with color. After that I am ttrying to draw other bitmap and I want the current state be something like a background and when I touch the screen I want to draw a bitmap on this possition and when I am trying to draw a bitmap on touch location the canvas goes back to the previous state with the draws.

Here is my code:

package com.inveitix.android.clue.ui.views;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.inveitix.android.clue.R;
import com.inveitix.android.clue.cmn.Door;
import com.inveitix.android.clue.cmn.MapPoint;

import java.util.ArrayList;
import java.util.List;

public class DrawingView extends SurfaceView {

    private static final String TAG = "DrawingView";
    private static final float DOOR_SIZE = 30;

    private Paint paint;
    private Canvas canvas;
    private int maxHeight;
    private int maxWidth;
    private SurfaceHolder surfaceHolder;
    private List<MapPoint> shape;
    private List<Door> doors;
    private float ratio;
    private boolean isFloorFinished;
    private boolean isDoorSelected;
    Path path;

    public DrawingView(Context context) {
        super(context);
        init();
    }

    public DrawingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void setIsDoorSelected(boolean isDoorSelected) {
        this.isDoorSelected = isDoorSelected;
    }

    public void setIsFloorFinished(boolean isFloorFinished) {
        this.isFloorFinished = isFloorFinished;
    }

    private void init() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        isFloorFinished = false;
        surfaceHolder = this.getHolder();
        prepareCanvas();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        shape = new ArrayList<>();
        doors = new ArrayList<>();
    }

    private void prepareCanvas() {
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            public void surfaceDestroyed(SurfaceHolder holder) {
            }

            public void surfaceCreated(SurfaceHolder holder) {
                canvas = holder.lockCanvas();
                canvas.drawColor(Color.WHITE);
                holder.unlockCanvasAndPost(canvas);
            }

            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }
        });
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
        int minh = getPaddingBottom() + getPaddingTop() + getSuggestedMinimumHeight();
        this.maxWidth = resolveSizeAndState(minw, widthMeasureSpec, 1);
        this.maxHeight = resolveSizeAndState(minh, heightMeasureSpec, 1);
        if (ratio != 0) {
            maxHeight = (int) (maxWidth / ratio);
        }
        Log.i(TAG, "onMeasure width:" + maxWidth);
        Log.i(TAG, "onMeasure height:" + maxHeight);
        setMeasuredDimension(maxWidth, maxHeight);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN && !isFloorFinished) {
            if (surfaceHolder.getSurface().isValid()) {
                shape.add(new MapPoint(event.getX(), event.getY()));
                canvas = surfaceHolder.lockCanvas();
                canvas.drawColor(Color.WHITE);
                for (MapPoint point : shape) {
                    canvas.drawCircle(point.getX(), point.getY(), 10, paint);
                }
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        } else if (event.getAction() == MotionEvent.ACTION_DOWN && isDoorSelected) {
            if (surfaceHolder.getSurface().isValid()) {
                Door door = new Door();
                door.setConnectedTo("door1"); //this is for test
                door.setX(event.getX());
                door.setY(event.getY());
                doors.add(door);
                canvas = surfaceHolder.lockCanvas();
                drawDoors(canvas);
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
        return false;
    }

    public void drawFloor() {
        Bitmap bmpFloorPattern = BitmapFactory.decodeResource(getResources(), R.drawable.floor_pattern6);
        BitmapShader patternBMPshader = new BitmapShader(bmpFloorPattern,
                Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        canvas = surfaceHolder.lockCanvas();
        path = new Path();
        path.reset();

        if (shape != null) {
            path.moveTo(shape.get(0).getX(), shape.get(0).getY());
            alignPoints(path);
            canvas.drawColor(Color.WHITE);
            for (int i = 0; i < shape.size(); i++) {
                path.lineTo(shape.get(i).getX(), shape.get(i).getY());
            }
        }
        paint.setShader(patternBMPshader);
        path.close();
        canvas.drawPath(path, paint);
        paint.setShader(null);
        surfaceHolder.unlockCanvasAndPost(canvas);
    }

    public void drawDoors(Canvas canvas) {
        Bitmap bmpDoor = BitmapFactory.decodeResource(getResources(), R.drawable.door32);
        paint.setFilterBitmap(true);
        if (doors != null && doors.size() > 0) {
            for (Door door : doors) {
                canvas.drawBitmap(bmpDoor, door.getX() - DOOR_SIZE, door.getY() - DOOR_SIZE, null);
            }
        }
    }

    private void alignPoints(Path path) {
        MapPoint previousPoint = null;
        for (int i = 0; i < shape.size(); i++) {
            float x = shape.get(i).getX();
            float y = shape.get(i).getY();
            if (previousPoint != null) {
                float deltaX = Math.abs(x - previousPoint.getX());
                float deltaY = Math.abs(y - previousPoint.getY());
                if (Math.max(deltaX, deltaY) == deltaX) {
                    x = previousPoint.getX();
                } else {
                    y = previousPoint.getY();
                }
            }
            path.lineTo(x, y);
            previousPoint = shape.get(i);
        }
    }

    public void setWidthToHeightRatio(float ratio) {
        this.ratio = ratio;
        maxHeight = (int) (maxWidth / ratio);
        invalidate();
        requestLayout();
    }
}

Any ideas how to draw over the drawn background ?

I found it I have to draw doors in the same time with the floor so I did this changes:

@Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN && !isFloorFinished) {
            if (surfaceHolder.getSurface().isValid()) {
                shape.add(new MapPoint(event.getX(), event.getY()));
                canvas = surfaceHolder.lockCanvas();
                canvas.drawColor(Color.WHITE);
                for (MapPoint point : shape) {
                    canvas.drawCircle(point.getX(), point.getY(), 10, paint);
                }
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        } else if (event.getAction() == MotionEvent.ACTION_DOWN && isDoorSelected) {
            if (surfaceHolder.getSurface().isValid()) {
                Door door = new Door();
                door.setConnectedTo("door1"); //this is for test
                door.setX(event.getX());
                door.setY(event.getY());
                doors.add(door);
                drawFloor();
            }
        }
        return false;
    }

    public void drawFloor() {
        Bitmap bmpFloorPattern = BitmapFactory.decodeResource(getResources(), R.drawable.floor_pattern6);
        BitmapShader patternBMPshader = new BitmapShader(bmpFloorPattern,
                Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        canvas = surfaceHolder.lockCanvas();
        path = new Path();
        path.reset();

        if (shape != null) {
            path.moveTo(shape.get(0).getX(), shape.get(0).getY());
            alignPoints(path);
            canvas.drawColor(Color.WHITE);
            for (int i = 0; i < shape.size(); i++) {
                path.lineTo(shape.get(i).getX(), shape.get(i).getY());
            }
        }
        paint.setShader(patternBMPshader);
        path.close();
        canvas.drawPath(path, paint);
        paint.setShader(null);
        if(doors.size() > 0) {
            drawDoors();
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM