Android绘制一条线来跟随你的手指

时间:2010-11-29 02:24:30

标签: android drawing ontouchevent

我想要做的是绘制一条跟随我的手指的线条。我创造了 自定义视图,我有onTouchEvent()可用。

我可以在onDraw()方法中绘制一条静态线而不会有太多麻烦。

我不确定如何在我的手指移动时画出画线。

  public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            Log.e(TAG, " - DOWN -");
            Log.e(TAG, " getX: " + event.getX());
            break;
        }
        case MotionEvent.ACTION_UP: {
            Log.e(TAG, " - UP -");
            Log.e(TAG, " getX: " + event.getX());
            break;
        }
        }
        return true;
    }

你们这些人一直在做的任何暗示可以给出什么?

我是否需要在onTouchEvent()上设置坐标并不断使视图无效 所以小线段画出来了吗?

最后我只想用手指在屏幕上涂鸦 这个实验。

6 个答案:

答案 0 :(得分:30)

您只跟踪上下事件。跟踪ACTION_MOVE事件。请注意它会连续跟踪,即使该人的手指没有明显移动。你的代码应该是这样的:

ACTION_DOWN:存储位置。

ACTION_MOVE:如果位置与存储位置不同,则从存储位置绘制一条线到当前位置,并将存储位置更新为当前位置。

ACTION_UP:停止。

在ACTION_MOVE位中,检查位置是否与存储位置相距至少2或3个像素可能是个好主意。如果您要存储所有绘图点,以便稍后可以对数据执行某些操作,那么可能会将其增加到10像素,这样您就不会为简单的线条获得数百个点。

答案 1 :(得分:9)

这就是我最终做的事情。希望这有助于其他一些初学者开始。

我有一个Sprite类,表示我想在屏幕上移动的对象:

   public class Sprite {
    private final String TAG = "Sprite";
    private Drawable drawable;
    private int x; // the X coordinate
    private int y; // the Y coordinate
    private boolean touched; // if droid is touched/picked up
    private Speed speed; // the speed with its directions

    public Sprite(Drawable drawable, int x, int y) {
        this.drawable = drawable;
        this.x = x;
        this.y = y;
        this.speed = new Speed();
    }

    public void draw(Canvas canvas) {
        drawable.setBounds(new Rect(x, y, x+drawable.getIntrinsicWidth(), y+drawable.getIntrinsicHeight()));
        drawable.draw(canvas);
    }

    public void move() {
        if (!touched) {
            x += (speed.getXv() * speed.getxDirection());
            y += (speed.getYv() * speed.getyDirection());
        }
    }

    public void handleActionDown(int eventX, int eventY) {
        if (eventX >= (x - bitmap.getWidth() / 2) && (eventX <= (x + bitmap.getWidth() / 2))) {
            if (eventY >= (y - bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {
                // droid touched
                setTouched(true);
            } else {
                setTouched(false);
            }
        } else {
            setTouched(false);
        }
    }
}

然后我有一个主游戏循环。它循环并调用我的mainPanel的渲染和更新方法,如下所示:

    public void render(Canvas canvas) {
    canvas.drawColor(Color.BLACK);
    sprite.draw(canvas);
}

public void update() {
    sprite.move();
}

精灵移动的位置在动作事件捕获中处理:

        if (event.getAction() == MotionEvent.ACTION_MOVE) {
        // the gestures
        if (sprite.isTouched()) {
            sprite.setX((int) event.getX());
            sprite.setY((int) event.getY());
        }
    }

希望这很有帮助。如果我裁掉太多而且你有什么东西不让我知道。

下一步,让对象跟随线!

答案 2 :(得分:3)

触摸事件与可检索的指针计数列表相关联,如下所示:

     int p = event.getPointerCount();

迭代这些和绘图点可以导致连续 要显示的行

if (event.getAction() == MotionEvent.ACTION_MOVE
    || event.getAction() == MotionEvent.ACTION_DOWN) {

  int p = event.getPointerCount();
     for (int i = 0; i < p; i++) { 
       c.drawPoint(event.getX(i), event.getY(i), paint);
     }
}

假设paint已经设置且c是画布,可能需要在绘制之前锁定(例如,在多线程应用程序中)。

答案 3 :(得分:2)

对于新手,此代码将帮助您创建涂鸦图像并将其导出为Png图像 这里是Complete CODE,活动类包含了一个View类..

public class MainActivity extends Activity {
    private Bitmap DrawBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint DrawBitmapPaint;
    RelativeLayout Rl;
    CustomView View;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View = new CustomView(this);
        Rl = (RelativeLayout) findViewById(R.id.Rel);
        Rl.addView(View);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(getResources()
                .getColor(android.R.color.holo_green_dark));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(20);

    }

    private Paint mPaint;

    public class CustomView extends View {

        @SuppressWarnings("deprecation")
        public CustomView(Context c) {

            super(c);
            Display Disp = getWindowManager().getDefaultDisplay();
            DrawBitmap = Bitmap.createBitmap(Disp.getWidth(), Disp.getHeight(),
                    Bitmap.Config.ARGB_4444);

            mCanvas = new Canvas(DrawBitmap);

            mPath = new Path();
            DrawBitmapPaint = new Paint(Paint.DITHER_FLAG);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            setDrawingCacheEnabled(true);
            canvas.drawBitmap(DrawBitmap, 0, 0, DrawBitmapPaint);
            canvas.drawPath(mPath, mPaint);
            canvas.drawRect(mY, 0, mY, 0, DrawBitmapPaint);
        }

        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;

        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }

        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
                mX = x;
                mY = y;
            }
        }

        private void touch_up() {
            mPath.lineTo(mX, mY);

            mCanvas.drawPath(mPath, mPaint);

            mPath.reset();
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
            }
            return true;
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        mPaint.setXfermode(null);
        switch (item.getItemId()) {
        case R.id.erase: 
               mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
               break;
        case R.id.DELETE: 
             View =  new CustomView(this);
               break;
        case R.id.draw: 
               mPaint.setXfermode(null);

               break;
        case R.id.Save:
            String pattern = "mm ss";
            SimpleDateFormat formatter = new SimpleDateFormat(pattern);
            String time = formatter.format(new Date());
            String path = ("/d-codepages" + time + ".png");

            File file = new File(Environment.getExternalStorageDirectory()
                    + path);

            try {
                DrawBitmap.compress(Bitmap.CompressFormat.PNG, 100,
                        new FileOutputStream(file));
                Toast.makeText(this, "File Saved ::" + path, Toast.LENGTH_SHORT)
                        .show();
            } catch (Exception e) {
                Toast.makeText(this, "ERROR" + e.toString(), Toast.LENGTH_SHORT)
                        .show();
            }

        }
        return super.onOptionsItemSelected(item);
    }

}

答案 4 :(得分:1)

另请查看Java Path类。当您在屏幕上移动手指时,可以使用此方法绘制路径。每次更新时(无论如何实现这一点 - 例如,上次更新中的每个像素都很多),您可以将x,y坐标添加到路径中,然后通过循环重新渲染总路径。只是我现在正在玩的想法。

答案 5 :(得分:1)

已经有一段时间了,但这篇文章仍然有一些观点,所以我想我会发布一些有用的东西:

关于如何使对象遵循一条线的教程: http://www.rengelbert.com/tutorial.php?id=182

这是一个很好的免费游戏引擎,上面的教程也使用: http://libgdx.badlogicgames.com/

希望这可以帮助别人!