2013-06-23 5 views
10

Ich erstelle eine benutzerdefinierte Ansicht, die eine Art Bogen Schieberegler Fortschrittsansicht ist. Ich kann mehr oder weniger des Bogens basierend auf, wo der Benutzer berührt (auf dem x axis), indem ich den Sweep berechne, tue ich dies, indem ich zuerst den Prozentsatz berechne, wo der Benutzer entlang der X-Achse berührte. 0,0% wäre ganz nach links und 100% wäre ganz nach rechts.Benutzerdefinierte Ansicht drawArc, erkennen Benutzer berühren auf zeichnen Weg des Bogens

Ich möchte einen Schritt weiter gehen, anstatt den Bogen basierend auf der x-Koordinate zu zeichnen, die der Benutzer drückt, möchte ich es nur bewegen, wenn der Benutzer den tatsächlichen Lichtbogen-Zeichnen-Pfad berührt, so ist es realistischer . Ich bin noch neu, um benutzerdefinierte Ansichten und meine Mathe begrenzt ist, aber wenn ich ein paar Tipps bekommen wäre ich dankbar Dank

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

Antwort

9

Ist diese Arbeit für Sie? Sie brauchen nicht viel Mathematik. Sie können den Abstand des Berührungspunkts von der Mitte Ihres Bogens berechnen (es ist ein Kreis, so dass es einfach ist) und vergleichen Sie diesen mit dem Radius, den Sie verwenden. Das wird Ihnen sagen, ob der Punkt auf dem Bogen ist (fast, siehe unten für den vollständigen Fall).

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

Ich wünschte, ich könnte wählen 2 Top-Antworten, ich werde oben klicken Sie dank einer Million – brux

+0

keine Sorgen, froh, zu helfen :) – Plato

+0

Ich änderte meine Meinung und machte dies richtig, da ich immer noch havnt voll meinen Kopf um es aber Ihre Code funktioniert, bist du irc zufällig? – brux

11

Ich will es nur machen zu bewegen, wenn der Benutzer berührt auf dem tatsächlichen Bogen draw Weg

Zu Beginn onTouchEvent() Sie, ob xPosition und yPosition prüfen müssen, sind einige Bedingungen zu erfüllen . Wenn ja, machst du das Zeug, was du gerade machst. Wenn nein, return true.

Zustand:

Wir ob x überprüfen mögen, y in diesem grauen Bogen Hintergrund ist:

enter image description here

Läßt sich einen Abstand von (x, y) zu diesem Punkt berechnen (a, b) in der Mitte:

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

distance() ist eine einfache euklidische dista NOA zwischen den Punkten (x, y) und (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 ist in diesem Grau arc Hintergrund, wenn y > Y && dist >= r && dist <= R.

+3

+1 für die Zeichnung :) – Plato

Verwandte Themen