Android 画一条线来跟随你的手指

发布于 2024-10-05 02:11:01 字数 793 浏览 0 评论 0原文

我想做的是画一条沿着我的手指的线。我已经创建了 自定义视图,并且我有一个可以工作的 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() 上设置坐标并不断使视图无效 那么小线段画出来了吗?

最后,我只是希望能够用我的手指在屏幕上进行涂鸦 这个实验。

What I want to do is to draw a line that will follow my finger. I've created
a custom view, and I have an onTouchEvent() that works.

I can draw a static line in the onDraw() method without much trouble.

I'm not really sure how to get the line to draw as my finger moves though.

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

Any hints you guys who have been doing it a while can give?

Do I need to set coordinates on the onTouchEvent() and constantly invalidate the view
so the little line segments draw?

In the end I just want to be able to basically doodle on the screen using my finger for
this experiment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

帝王念 2024-10-12 02:11:01

您仅跟踪上升和下降事件。也跟踪 ACTION_MOVE 事件。请注意,即使该人的手指没有明显移动,它也会连续跟踪。您的代码应该如下所示:

ACTION_DOWN:存储位置。

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

ACTION_UP:停止。

在 ACTION_MOVE 位中,最好检查该位置是否距存储位置至少 2 或 3 个像素。如果您要存储所有绘图点,以便稍后可以对数据进行处理,那么可以将其增加到 10 个像素,这样您就不会在一条简单的线条上得到数百个点。

You're only tracking the up and down events. Track the ACTION_MOVE event too. Beware that it will track continuously, even if the person's finger isn't apparently moving. Your code should go something like this:

ACTION_DOWN: Store position.

ACTION_MOVE: If position is different from stored position then draw a line from stored position to current position, and update stored position to current.

ACTION_UP: Stop.

In the ACTION_MOVE bit, it might be a good idea to check if the position is at least 2 or 3 pixels away from the stored position. If you're going to store all of the plot points, so you can do something with the data later, then maybe increase that to 10 pixels so you don't end up with hundreds of points for a simple line.

娇纵 2024-10-12 02:11:01

这就是我最终所做的。希望这可以帮助其他一些初学者入门。

我有一个 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());
        }
    }

希望这有帮助。如果我修剪得太多而有些东西你没有得到,请告诉我。

下一步,让对象沿着线移动!

Here's what I ended up doing. Hopefully this helps some other beginners out there get started.

I have a Sprite class that represents the object I want to move on the screen:

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

Then I have a main game loop. That loops through and calls my mainPanel's render and update methods which look like this:

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

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

The position of where the sprite will move is handled in the motion event capture:

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

Hopefully that is helpful. If I trimmed out too much and there is something you don't get let me know.

Next step, making the object follow the line!

香橙ぽ 2024-10-12 02:11:01

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

     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 是画布,在其上绘图之前可能需要锁定(例如,在多线程应用程序中)。

A touch event is associated with a list of pointer counts retrievable like the following:

     int p = event.getPointerCount();

iterating over these and drawing points can cause a continuous
line to appear

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

Assuming paint is already set and c is the canvas, which may need to be locked (Eg- in a multithread application), prior to drawing on it.

亣腦蒛氧 2024-10-12 02:11:01

对于新手来说,此代码将帮助您创建涂鸦图像并将其导出为 Png 图像
这里是 完整代码,这个 Activity 类也包含一个 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);
    }

}

For newbies this code will help you to create doodle image and export it into Png image
here Is the Complete CODE and this the Activity Class With contains a View class too..

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

}
岁月染过的梦 2024-10-12 02:11:01

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

Also check out the Java Path class. You can use this to draw path...as you move your finger across the screen. with every update(however you implement this - every so many pixels from the last update for example) you add the x,y coordinate to your Path and re-render the total path through a loop. just an idea that I am playing around with now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文