2010-11-29 14 views
14

Lo que quiero hacer es dibujar una línea que siga mi dedo. Creé una vista personalizada, y tengo un onTouchEvent() que funciona.Android dibujando una línea para seguir su dedo

Puedo dibujar una línea estática en el método onDraw() sin muchos problemas.

No estoy muy seguro de cómo dibujar la línea a medida que avanza mi dedo.

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

¿Alguna sugerencia que ustedes que han estado haciendo durante un tiempo pueden dar?

¿Necesito establecer coordenadas en el onTouchEvent() e invalidar constantemente la vista para que dibujen los segmentos de las líneas pequeñas?

Al final solo quiero poder garabatear básicamente en la pantalla con el dedo para este experimento.

+0

Publicado una respuesta, pero por favor, intente encontrar una respuesta por su cuenta primero. Como puede ver en mi respuesta, ya hay muchas cosas así, la Búsqueda de Google es su amiga. – AGrunewald

Respuesta

29

Solo está rastreando los eventos de arriba y abajo. Rastrea el evento ACTION_MOVE también. Tenga en cuenta que hará un seguimiento continuo, incluso si el dedo de la persona no se mueve aparentemente. Su código debería ser algo como esto:

ACTION_DOWN: posición de la tienda.

ACTION_MOVE: Si la posición es diferente de la posición almacenada, trace una línea desde la posición almacenada a la posición actual y actualice la posición almacenada a la actual.

ACTION_UP: Stop.

En el bit ACTION_MOVE, podría ser una buena idea verificar si la posición está al menos a 2 o 3 píxeles de distancia de la posición almacenada. Si vas a almacenar todos los puntos de la trama, para que puedas hacer algo con los datos más adelante, entonces tal vez aumente eso a 10 píxeles para que no tengas cientos de puntos para una línea simple.

+0

¡Buena información! Jugaré con esto un poco esta noche. El trazado real de la línea se debe hacer en el método onDraw, ¿es correcto? Voy a almacenar la información de línea en las acciones, pero luego invoco invalidar para activar el onDraw para hacer el trabajo ¿verdad? – jacklin

+0

Oh sí, ciertamente, no harías tu dibujo en el controlador de eventos. Necesitará almacenar los puntos de extracción de alguna manera y luego dibujar la (s) línea (s) en onDraw. –

+0

¡Funciona muy bien ahora! Gracias. Te daría un +1 pero aparentemente no estoy lo suficientemente alto :( – jacklin

9

Esto es lo que terminé haciendo. Espero que esto ayude a otros principiantes a empezar.

tengo una clase Sprite que representa el objeto que desea mover en la pantalla:

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

entonces tengo un bucle principal del juego. Que recorra y pide mis mainPanel de prestar y métodos de actualización que se parecen a esto:

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

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

La posición de dónde se moverá se maneja el sprite en la captura de eventos de movimiento:

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

Esperemos que sea útil . Si recorté demasiado y hay algo que no entiendo, házmelo saber.

Siguiente paso, haciendo que el objeto siga la línea!

+2

¿Qué hay en la clase de velocidad? ¿Puedes explicarlo? –

3

Un evento de contacto está asociado a una lista de puntero recuentos recuperables como la siguiente:

 int p = event.getPointerCount(); 

iteración sobre estos y puntos de giro puede hacer que aparezca una línea continua

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

Suponiendo paint ya está configurado y c es el lienzo, que puede necesitar bloquearse (por ejemplo, en una aplicación de subprocesos múltiples), antes de dibujar en él.

1

También consulte la clase de ruta de Java. Puede usar esto para dibujar la ruta ... a medida que mueve su dedo por la pantalla. con cada actualización (independientemente de cómo implemente esto, cada tantos píxeles de la última actualización, por ejemplo) agrega la coordenada x, y a su ruta y vuelve a procesar la ruta total a través de un bucle. solo una idea con la que estoy jugando ahora.

+0

No he jugado con este proyecto en un tiempo, pero gracias por la información! Si lo consigues funcionando pega tu código si no importa, ¡gracias de nuevo! – jacklin

2

Para los novatos este código le ayudará a crear imagen Doodle y exportarlo imagen PNG aquí en ¿Está la Complete CODE y esto la clase con actividades contiene una clase Ver también ..

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

} 
Cuestiones relacionadas