android - 在 Canvas 上绘制位图/图像,用户在屏幕上触摸

标签 android bitmap android-canvas surfaceview touch-event

我是安卓新手。我想在用户触摸的地方绘制位图。这会在触摸时创建一个位图,但只会创建一个位图,并且在用户触摸时会替换并移动到新位置。我想在新的触摸位置上绘制一个新的位图,将旧的位图留在原处,并且可以将任何位图移动/拖动到新位置..请帮助

public class SurfaceViewEx extends Activity implements OnTouchListener {

    OurView v;
    Bitmap cloud;
    float x, y;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        cloud = BitmapFactory.decodeResource(getResources(), R.drawable.cloud);
        v = new OurView(this); //Passing the context of this class
        v.setOnTouchListener(this);
        x = y = 0;
        setContentView(v);
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        v.pause();
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        v.resume();
    }

    //It will handle drawing
    public class OurView extends SurfaceView implements Runnable {

        Thread t = null;
        SurfaceHolder holder; //
        boolean isItOk = false;

        public OurView(Context context) {
            super(context);
            //To make sure we can draw on canvas and surface is valid
            holder = getHolder();
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (isItOk == true) {
                //Perform canvas drawing
                if(!holder.getSurface().isValid()) {
                    //Call back to while ..
                    continue; 
                }
                //Lock the canvas, and unlock after drawing
                Canvas c = holder.lockCanvas();
                c.drawARGB(255, 0, 0, 0);
                c.drawBitmap(cloud, x - (cloud.getWidth()/2), y - (cloud.getHeight()/2), null);
                holder.unlockCanvasAndPost(c);
                }
        }

        public void pause() {
            isItOk = false;
            while(true) {
                try {
                    //Blocks the current thread until the receiver finishes 
                    //the execution and dies
                    t.join(); 

                } 
                catch (InterruptedException e){
                    e.printStackTrace();
                }
                break;
            }
            //t = null;
        }

        public void resume() {
            isItOk = true; //Able to draw
            t = new Thread(this);
            t.start();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent me) {
        // TODO Auto-generated method stub

        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        switch(me.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = me.getX();
                y = me.getY();
                break;
            case MotionEvent.ACTION_UP:
                //Same code
            case MotionEvent.ACTION_MOVE:
                //Same code
        }
        return true;
    }
}

最佳答案

我会建议一个面向对象的解决方案:

class DragableObject {
  int x;
  int y;
  Bitmap bitmap;

  public DragableObject(Bitmap bitmap, int x, int y) {
    this.x = x;
    this.y = y;
    this.bitmap = bitmap;
  }

  public void draw(Canvas c) {
    c.drawBitmap(bitmap, x, y);
  } 

  public boolean grab(int touchX, int touchY) {
    // TODO check if object is touched (coordinates are inside objects bounds), return value accordingly
  }

  public void drag(int deltaX, int deltaY){
    this.x += deltaX;
    this.y += deltaY;
  }
}

比在你的表面类:

DragableObject selectedObject = null;
int previousX;
int previousY;
List<DragableObject> objects = new ArrayList<DragableObject>();

public boolean onTouch(View v, MotionEvent me) {
  int x = me.getX();
  int y = me.getY();
  switch(me.getAction()) {
  case MotionEvent.ACTION_DOWN:
    previousX = x;
    previousY = y;
    for (DragableObject object : objects) {
      if (object.grab()) {
        selectedObject = object;
        break;
      }
    }          
    break;
  case MotionEvent.ACTION_UP:
    selectedObject = null;
    break;
  case MotionEvent.ACTION_MOVE:
    if (selectedObject != null) {
      selectedObject.drag(x - previousX, y - previousY);
      previousX = x;
      previousY = y;
    }
    break;
   }
  return true;
}

比起在表面上绘制时,只需绘制对象: ...

  for (DragableObject object : objects) {
    object.draw(c);
  }

...

关于android - 在 Canvas 上绘制位图/图像,用户在屏幕上触摸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18702146/

相关文章:

Android相机位图内存泄漏

尝试将位图加载到 imageView 时出现 java.lang.OutOfMemoryError

android - 如何在带有动画的 Android Canvas 上绘制路径?

android - 如何在 Canvas 上绘制可变宽度的路径

Android - 如何沿路径设置动画颜色变化

android - 如何在 Studio 项目中禁用 Jacoco 测试覆盖率

java - 缺少 Android JRE 系统库 (java.awt.*)

pdf - 如何将自定义半色调应用于 PDF 文件到位图的 ghostscript 转换

Android 相机设置PictureSize 扭曲相机预览

Android 在单击按钮时从 url 加载图像