2013-06-23 13 views
10

Sto creando una vista personalizzata che è una sorta di vista di avanzamento del cursore ad arco.Posso disegnare più o meno dell'arco in base a dove l'utente tocca (sulla x asse) calcolando lo sweep, lo faccio calcolando prima la percetage in cui l'utente ha toccato l'asse x. 0% sarebbe completamente a sinistra e 100% sarebbe tutto a destra.Custom View drawArc, rileva il tocco dell'utente sul tracciato dell'arco

Voglio fare un ulteriore passo avanti, invece di disegnare l'arco in base alla coordinata x che l'utente preme, voglio farlo muovere solo quando l'utente tocca il tracciato arco reale, quindi è più realistico . Sono ancora nuovo visualizzazioni personalizzate e le mie matematica è limitata, ma se ho alcuni suggerimenti sarei grato grazie

how it looks when user moves there finger on the area of the rectangle as a percentage along the x axis

class ArcProgress extends View { 

    Context cx; 
    float width; 

    float height; 
    float center_x, center_y; 
    final RectF oval = new RectF(); 
    final RectF touchArea = new RectF(); 

    float sweep = 0; 
    float left, right; 
    int percent = 0; 

    public ArcProgress(Context context) { 
     super(context); 
     cx = context; 

    } 

    public int getPercentage() { 
     return percent; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     setBackgroundColor(0xfff0ebde); 

     width = (float) getWidth(); 
     height = (float) getHeight(); 

     float radius; 

     if (width > height) { 
      radius = height/3; 
     } else { 
      radius = width/3; 
     } 

     Paint paint = new Paint(); 
     paint.setAntiAlias(true); 
     paint.setColor(0xffd2c8b6); 
     paint.setStrokeWidth(35); 

     paint.setStyle(Paint.Style.STROKE); 

     center_x = width/2; 
     center_y = height/2; 

     left = center_x - radius; 
     float top = center_y - radius; 
     right = center_x + radius; 
     float bottom = center_y + radius; 

     oval.set(left, top, right, bottom); 

      //this is the background arc, it remains constant 
     canvas.drawArc(oval, 180, 180, false, paint); 

     paint.setStrokeWidth(10); 
     paint.setColor(0xffe0524d); 
      //this is the red arc whichhas its sweep argument manipulated by on touch 
     canvas.drawArc(oval, 180, sweep, false, paint); 

    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 

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

      float xPosition = event.getX(); 
      float yPosition = event.getY(); 
      if (oval.contains(xPosition, yPosition)) { 

       float x = xPosition - left; 
       float s = x * 100; 
       float b = s/oval.width(); 
       percent = Math.round(b); 
       sweep = (180/100.0f) * (float) percent; 

       invalidate(); 

      } else { 
       if (xPosition < left) { 
        percent = 0; 

        sweep = (180/100.0f) * (float) percent; 
        invalidate(); 
       } 
       if (xPosition > right) { 
        percent = 100; 

        sweep = (180/100.0f) * (float) percent; 
        invalidate(); 
       } 
      } 
     } 

     return true; 
    } 
} 

risposta

9

Fa questo lavoro per te? Non hai bisogno di molti Math. Puoi calcolare la distanza del punto di contatto dal centro dell'arco (è un cerchio quindi è facile) e confrontarlo con il raggio che stai utilizzando. Questo ti dirà se il punto è sull'arco (quasi, vedi sotto per caso completo).

Point touchEv = ...; 
Point circleCenter = ...; 

//the radius of the circle you used to draw the arc 
float circleRadius = ...; 
//how far from the arc should a touch point treated as it's on the arc 
float maxDiff = getResources().getDimension(R.dimen.max_diff_dp); 

//calculate the distance of the touch point from the center of your circle 
float dist = Math.pow(touchEv.x-circleCenter.x,2) + Math.pow(touchEv.y- circleCenter.y,2) 
dist = Math.sqrt(dist); 

//We also need the bounding rect of the top half of the circle (the visible arc) 
Rect topBoundingRect = new Rect(circleCenter.x - circleRadius, 
      circleCenter.y - circleRadius, 
      circleCenter.x + circleRadius, 
      circleCenter.y); 


if (Math.abs(dist - circleRadius) <= maxDiff && 
    topBoundingRect.contains(touchEv.x, touchEv.y)) { 
    // the user is touching the arc 

} 
+0

Vorrei poter scegliere 2 risposte migliori, farò clic su di voi grazie mille – brux

+0

no preoccupazioni, felice di aiutare :) – Plato

+0

ho cambiato idea e fatto questo corretto dal momento che ho ancora havnt completamente la mia testa intorno ma il tuo funziona il codice, sei su irc per caso? – brux

11

voglio farlo muovere solo quando l'utente tocca l'attuale arco percorso pareggio

All'inizio del onTouchEvent() è necessario verificare se xPosition e yPosition stanno compiendo alcune condizioni . Se sì, fai le cose che stai facendo ora. Se no, return true.

Condizione:

Vogliamo controllare se x, y sono in quell'arco sfondo grigio:

enter image description here

Calcoliamo una distanza da (x, y) a quel punto (a, b) al centro:

final dist = distance(x, y, a, b) 

distance() è un semplice dista euclidea SNO tra i punti (x, y) e (a, b):

double distance(int x, int y, int a, int b) 
{ 
    return Math.sqrt((x - a) * (x - a) + (y - b) * (y - b)); 
} 

x, y sono in quell'arco sfondo grigio, se y > Y && dist >= r && dist <= R.

+3

+1 per il disegno :) – Plato

Problemi correlati