Android Canvas - drawText - Update Text in ActionListener

search@info

Mitglied
Hi,

ich zeichne mehrere Texte in ein Canvas. Das Canvas reagiert auf einen OnTouchListener.
Wie bekomme ich in der Action Methode den Text raus, den ich berührt habe?

Wenn ich ein Layout setzen würde, kann ich es über die ID identifizieren.
Die ID wäre dann dieselbe ID, wie ich in meinem ArrayList Container definiert habe. Den Text kann ich dann über die ID identifizieren.

Eine solche eine Möglichkeit habe ich beim Canvas Text zeichnen nicht gefunden. Ich habe was von einem TextRender gelesen, aber sowie ich das verstanden habe ist das für ein GLSurfface und als Neuling werde ich von der Vielzahl an Parametern erschlagen und hoffe eine andere Lösung zufinden.

Java:
//Code in Action Class

public void definePositions{
 //[Position definition for X + Y]
LineView lineView = new LineView(this,linePosX, linePosY);
		lineView.setOnTouchListener(this);
		branch_layout.addView(lineView);
}

//Inner Class from Action Class
private class LineView extends View {
		
		private float [] linePosX;
		private float [] linePosY;
		
        public LineView(Context context) {
			super(context);
		}
        public LineView(Context context, float linePosX[], float linePosY[]) {
			super(context);
			this.linePosX = linePosX;
			this.linePosY = linePosY;
			
		}
}
	@Override
		protected void onDraw(Canvas canvas) {
			// TODO Auto-generated method stub
			super.onDraw(canvas);
			Paint paint = new Paint();
			paint.setColor(Color.BLUE);
			paint.setAntiAlias(true);
			paint.setStrokeWidth(2);
			paint.setStyle(Paint.Style.FILL);

//8 Texte and unterschiedliche Positionen	
			for (int i = 0; i < linePosX.length; i++) {
				
				 canvas.drawText("test", linePosX[i], linePosY[i], paint);
				 canvas.drawLine(linePosX[i], linePosY[i], linePosX[i]+50, (float)linePosY[i], paint);

			}
		}

@Override
	public boolean onTouch(View v, MotionEvent event) {
//Wie kann ich den Text raus, den ich angeklickt habe?
}

Viele Grüße,

Saskia
 

schlingel

Gesperrter Benutzer
Die Frage ist wie du einen String aus deinen Ressourcen heraus bekommst, oder?

Also überall wo du einen Context hast, geht das leicht.
Java:
deinContext.getResources().getString(R.string.deinString);
 

search@info

Mitglied
Hi,

vielen Dank für die rasche Antwort. Soweit ich weiß ist R.string.name123 statisch und ich kann den Wert nicht nachträglich ändern, oder kann dynamisch neue strings hinzufügen, oder? Muss ich mal ausprobieren.

Die Situation ist folgende:
1. App starten mit Image in der Mitte, sonst nichts
2. User "touched" das Image -> String-Eingabe-Aufforderung und der String (Content variable) wird auf eine definierte x/y pos gesetzt. Wenn der User das Image wieder "touched" öffnet sich wieder eine Eingabe-Aufforderung -> String-Eingabe -> Neue x/y pos. (Im Radius um das Image im 45° Grad Abstand). Das kann der User 8 mal starten. (bis < 360°).
3. User "touched" bereits gemalten Text auf dem Canvas -> Eingabefeld öffnet sich wieder und der User kann den Text updated.

Diese Funktion habe ich bereits mit dem RelativeLayout und dynamischen LinearLayouts geschafft, ABER die X/Y pos gestalten sich bei dem Weg als extrem unhandlich (auch mit RelativeLayout.Params) und deswegen wäre es super, wenn man es auch malen und trotzdem identifizieren konnte, da man über diesem Weg ganz genau sagen kann was wo sein soll, wie hoch, breit, startxy, endxy etc...

Viele Grüße,

Saskia
 

schlingel

Gesperrter Benutzer
Ich würde mir an deiner Stelle die Bereiche und den dazugehörigen Text merken anstatt hier so eine Zwitter-Lösung zu bauen.

Ich würde mir eine kleine Datenstruktur schreiben die meine Labels enthält.

Java:
public class Label {
  public Label(String value, Recht bounds) {
    this.value = value;
    this.bounds = bounds;
  }

  private Rect bounds; // enthält die Koordinaten deines Strings und damit auch die Bounding Box

  private String value;

  // getter/setter
}

Mit dieser Klasse bildest du deine Labels ab. In deiner Klasse mit der zu zeichnest musst du noch beim setzen des Strings mit getTextBounds die Bounding-Box errechnen lassen.

Die Methode zum setzen könnte z.B. so aussehen:
Java:
public void addLabel(int xPos, int yPos, String label) {
  // das paint objekt bekommst du vom canvas.
  // nicht vergessen die parameter zu checken bei einer öffentlichen methode
  Rect bounding = new Rect();
  paint.getTextBounds(label.toCharArray(), 0, label.length(), bounding);
  // getTextBounds nimmt den Ursprung (0, 0) an, also müssen die Methoden-Parameter noch
  // dazu addiert werden.
  bounding.top += yPos;
  bounding.bottom += yPos;
  bounding.left += xPos;
  bounding.right += xPos;

  deineLabels.add(new Label(label, bounding));
}

Und in deiner Zeichnen-Methode gehst du nachdem das Bild gezeichnet wurde die Liste deineLabels durch und zeichnest mittels den Koordinaten in der bounding-Box.

Anschließend prüfst du in deinem Touch-Handler ob ein String von dir geschnitten wird. Dazu nimmst du die X u. Y-Koordinate des Touch-Events und nimmst diese als Mittelpunkt für ein Rect dessen Größe du bestimmen kannst. Ich würde das von der Auflösung abhängig machen und für ldpi 20px, mdpi 40px und hdpi 60px verwenden.

Mit diesem Rect kannst du mit intersect prüfen, ob sich der Touch-Punkt mit einem Label schneidet. Falls ja, startest du deinen Dialog zum neusetzen.
 

search@info

Mitglied
Hi,

VIELEN DANK für den tollen Hinweis. Ich war etwas in dem Layout Thema festgefahren. Ich habe deine Idee ausprobiert und bis jetzt sieht sie sehr vielversprechend aus und es ist um einiges handlicher als die Layouts. Die Methode intersect habe ich leider nicht aus laufen bekommen, aber ich habe mir dann mit folgender IF Bedingung ausgeholfen:

Java:
for (Item b : Controller.getInstance().getItem().getSubItems()) {
			if (event.getX() >= b.getRect().right &&
					event.getX() <= b.getRect().left &&
					event.getY() >= b.getRect().top &&
					event.getY() <= b.getRect().bottom){
				selectedItem = b;
				break;
			}
				
		}

Liebe Grüße,

Saskia
 

schlingel

Gesperrter Benutzer
Ich vermute, du hast die Koordinaten der Bounding Box deiner Klickfläche nicht an die Koordinaten des Touch-Events angepasst.

Aber hauptsache es funzt :)

PS: In Android sollte man immer for-Schleifen und keine foreach-Schleifen verwenden. Das hat den Sinn, das beim for-Aufruf intern Objekte für den Iterator angelegt werden und damit der GC auf den Plan gerufen wird.
Der frisst in diesem Fall nur unnötig Resourcen. Nicht so schlimm auf Geräten >= 2.3 da dort der GC auch async laufen kann, aber gerade bei den alten Geräten kann es einen ordentlichen Unterschied machen ob die App 300ms einfriert oder nicht.
 
Zuletzt bearbeitet:

search@info

Mitglied
Hi,

ich weiß eigentlich ist das Thema geschlossen, aber vllt darf ich mir trotzdem noch eine kurze Frage erlauben :p
Wenn ich in meinem TouchListener sage => Male den Text + Line auf das Canvas und ich dann beim 2. touch event einen neuen Text + Line an eine andere Position male muss ich den Text + Line aus dem 1 touch event immer mit malen, da es sonst verschwindet. Im TouchListener rufe ich die View methode invalidate auf, damit die onDraw Methode angestoßen wird.
Gibt es auch die Möglichkeit, dass man wirklich nur das neue malt und das "alte" bestehen bleibt?

Viele Grüße,

Saskia

PS: Danke für den Hinweis mit der Schleife, dann weiß ich was ich gleich morgen früh anpassen werde, da ich mit der Version 2.1 arbeite :)
 

schlingel

Gesperrter Benutzer
Kommt darauf an ob sich die Szenarie dynamisch ändert oder ob du immer nur neue Strich dazu zeichnest.

Wenn du ein statisches Bild hast, dem du nur Inhalte hinzufügst, kannst du immer das selbe BMP verwenden und darauf deine Striche zeichnen.

Wenn du aber Animationen oder eben das verschieben oder Löschen von Text realisieren möchtest, ist es klüger, dass beim jedem onDraw-Aufruf zu zeichnen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Arif Android Canvas wird nicht gezeichnet? Android & Cross-Platform Mobile Apps 0
Dechasa Android Android - Canvas NullpointException Android & Cross-Platform Mobile Apps 2
Z Canvas onDraw() Variablen muss in der Methode initialisiert werden Android & Cross-Platform Mobile Apps 1
F Mit Canvas zeichen und durch einen Timer aktualiesieren Android & Cross-Platform Mobile Apps 1
J Canvas mit dem Accelorometersensor bewegen Android & Cross-Platform Mobile Apps 0
E Android Zeichnen auf Canvas - Teilbereich als Bild speichern Android & Cross-Platform Mobile Apps 3
B onDraw Canvas jede Millisekunde aufrufen? Android & Cross-Platform Mobile Apps 12
G canvas in view anzeigen Android & Cross-Platform Mobile Apps 10
B Java ME Canvas Android & Cross-Platform Mobile Apps 2
J Java ME Canvas Klasse Gameloop und Funktion Android & Cross-Platform Mobile Apps 2
B Java ME Leere Canvas Seite Android & Cross-Platform Mobile Apps 21
P Java ME Texteingabe Canvas Android & Cross-Platform Mobile Apps 2
D wie geht Klassenvererbung von Canvas Klassen Android & Cross-Platform Mobile Apps 2
U Probleme mit der drawString Methode bei Canvas Android & Cross-Platform Mobile Apps 8
H Canvas kann nichts auf Graphics drawen Android & Cross-Platform Mobile Apps 3
M Textfeld in Canvas, implementation der keys aendern Android & Cross-Platform Mobile Apps 8
M Text in Canvas scrollen lassen Android & Cross-Platform Mobile Apps 13
M Wie in einer anderen "nicht canvas" klasse zeichne Android & Cross-Platform Mobile Apps 5
U ein texteingabefeld auf einem Canvas . Android & Cross-Platform Mobile Apps 2
A Problem: Canvas-Grösse Motorola RAZR v3r Android & Cross-Platform Mobile Apps 8
F Canvas Stringlänge Android & Cross-Platform Mobile Apps 2
B drawText verpixelt? Android & Cross-Platform Mobile Apps 2
B Android Fragement update im PageTabStrip Android & Cross-Platform Mobile Apps 2
K Löschen einer Tabelle bei PlayStore update Android & Cross-Platform Mobile Apps 2
J BatterieWidget update jede Sekunde Android & Cross-Platform Mobile Apps 1
T Android Layout Update Animation Android & Cross-Platform Mobile Apps 3
W Eclipse update - Systemprozess reagiert nicht mehr Android & Cross-Platform Mobile Apps 4

Ähnliche Java Themen

Neue Themen


Oben