代码之家  ›  专栏  ›  技术社区  ›  jacklin

安卓画一条线跟着你的手指

  •  15
  • jacklin  · 技术社区  · 14 年前

    我想做的是画一条线跟随我的手指。我创造了 自定义视图,我有一个 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 回复  |  直到 10 年前
        1
  •  30
  •   Andrew Smith    14 年前

    你只跟踪上下事件。也跟踪动作移动事件注意,即使手指没有明显移动,它也会持续追踪。你的代码应该是这样的:

    动作:存储位置。

    动作移动:如果位置与存储位置不同,则从存储位置到当前位置画一条线,并将存储位置更新为当前位置。

    动作:停止。

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

        2
  •  9
  •   jacklin    14 年前

    这就是我最后做的。希望这能帮助其他初学者开始学习。

    我有一个表示要在屏幕上移动的对象的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);
            }
        }
    }
    

    然后我有一个主要的游戏循环。循环调用主面板的render和update方法,如下所示:

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

    希望这是有帮助的。如果我剪得太多了,有什么事你不知道,告诉我。

    下一步,让物体沿着直线运动!

        3
  •  3
  •   heyNow    13 年前

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

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

        4
  •  2
  •   benka Csaba    10 年前

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

    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);
        }
    
    }
    
        5
  •  1
  •   cspam    13 年前

    还可以查看Java路径类。你可以用这个绘制路径…当你移动你的手指在屏幕上。每次更新(不管你实现了什么——比如上次更新的像素有这么多)你都会将x,y坐标添加到你的路径中,然后通过循环重新渲染整个路径。只是一个我正在玩弄的想法。

        6
  •  1
  •   jacklin    12 年前

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

    关于如何使对象跟随直线的教程: http://www.rengelbert.com/tutorial.php?id=182

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

    希望这能帮到别人!