2010-11-29 4 views
14

Ce que je veux faire est de tracer une ligne qui suivra mon doigt. J'ai créé une vue personnalisée, et j'ai un onTouchEvent() qui fonctionne.Android dessin d'une ligne pour suivre votre doigt

Je peux dessiner une ligne statique dans la méthode onDraw() sans trop de problèmes.

Je ne suis pas vraiment sûr de savoir comment tirer la ligne quand mon doigt bouge.

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

Tout allusions vous les gars qui l'ont fait un certain temps peut donner?

Ai-je besoin de définir les coordonnées sur le onTouchEvent() et d'invalider constamment la vue afin que les segments de ligne soient dessinés? En fin de compte, je veux juste pouvoir griffonner sur l'écran en utilisant mon doigt cette expérience.

+0

Publié une réponse, mais s'il vous plaît essayez de trouver une réponse par vous-même. Comme vous pouvez le voir dans ma réponse, il y a beaucoup de choses comme ça, Google Search est votre ami. – AGrunewald

Répondre

29

Vous effectuez uniquement le suivi des événements de montée et de descente. Suivez l'événement ACTION_MOVE aussi. Méfiez-vous qu'il suivra en continu, même si le doigt de la personne ne semble pas bouger. Votre code doit ressembler à ceci:

ACTION_DOWN: position de magasin. ACTION_MOVE: Si la position est différente de la position mémorisée, tracez une ligne de la position mémorisée à la position actuelle et mettez à jour la position enregistrée au courant.

ACTION_UP: Stop.

Dans le bit ACTION_MOVE, il peut être judicieux de vérifier si la position est éloignée d'au moins 2 ou 3 pixels de la position enregistrée. Si vous allez stocker tous les points de l'intrigue, vous pouvez donc faire quelque chose avec les données plus tard, alors peut-être augmenter cela à 10 pixels pour ne pas vous retrouver avec des centaines de points pour une simple ligne.

+0

Bonne info! Je vais jouer avec ça ce soir. Le dessin réel de la ligne devrait être fait dans la méthode onDraw si correct? Je vais stocker les informations de ligne dans les actions, mais ensuite appeler invalidate pour déclencher l'onDraw de faire le bon travail? – jacklin

+0

Oh oui, certainement, vous ne feriez pas votre dessin dans le gestionnaire d'événements. Vous aurez besoin de stocker les points de dessin d'une manière ou d'une autre, puis de tracer la ou les lignes dans onDraw. –

+0

Fonctionne bien maintenant! Merci. Je voudrais vous donner un +1 mais je ne suis apparemment pas classé assez haut :( – jacklin

9

Voici ce que j'ai fini par faire. J'espère que cela aidera d'autres débutants à démarrer.

J'ai une classe Sprite qui représente l'objet que je veux passer à l'écran:

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

Puis j'ai une boucle de jeu principal. Cela boucles à travers et appelle mes mainPanel de rendu et des méthodes de mise à jour qui ressemblent à ceci:

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

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

La position de l'endroit où l'image-objet mouvement est traité dans la capture d'événement de mouvement:

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

Espérons que UTILITÉ . Si je m'arrange trop et qu'il y a quelque chose que tu ne reçois pas, fais-le moi savoir.

Prochaine étape, faisant l'objet suivre la ligne!

+2

Ce qui était dans la classe de vitesse? Pouvez-vous s'il vous plaît expliquer –

3

Un événement tactile est associé à une liste de pointeur dénombre récupérables comme ce qui suit:

 int p = event.getPointerCount(); 

itérer sur ces derniers et des points de dessin peuvent causer une ligne continue à apparaître

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

En supposant paint est déjà défini et c est le canevas, qui peut avoir besoin d'être verrouillé (par exemple, dans une application multithread), avant de dessiner dessus.

1

Consultez également la classe Java Path. Vous pouvez l'utiliser pour tracer un chemin ... lorsque vous déplacez votre doigt sur l'écran. Avec chaque mise à jour (cependant vous implémentez ceci - tous les pixels de la dernière mise à jour par exemple) vous ajoutez la coordonnée x, y à votre chemin et re-rendre le chemin total à travers une boucle. juste une idée que je joue avec maintenant.

+0

Je n'ai pas joué avec ce projet depuis un moment, mais merci pour l'info! Si vous l'obtenez le travail coller votre code si vous ça ne fait rien, merci encore! – jacklin

2

Pour les débutants ce code vous aidera à créer doodle image et l'exporter dans l'image .png Voici le Complete CODE et cette catégorie d'activité avec contient une classe Voir aussi ..

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

} 
Questions connexes