onDraw wird nicht aufgerufen

AquaBall

Top Contributor
Ich habe ein seltsames Problem:
Mein selbst erstelltes CustomView funktioniert eigentlich wunderbar.

Im "root"-Layout(ScrollView) wird ein FrameLayout eingebettet, in das (im wesentlichen) ein (dynamisches) ImageView enthält.

Nun ist bekannt, dass bei onCreate und onResume die methoden getWidth() noch nichts zurückgeben.
Erst bei onDraw() oder onSizeChanged() der neuen View-classe ist die Größe bekannt. (Siehe auch http://www.java-forum.org/mobile-ge...uredwidth-gibt-nichts-zurueck.html#post900901)
Soweit funktioniert es auch.

Wenn ich mein FrameLayout nun aber noch in ein TableRow tiefer einbette, dann werden onDraw() oder onSizeChanged() nicht mehr aufgerufen.

Über rekursives getChildAt() stellt sich aber heraus, dass meinCustomView an der richtigen Stelle reingehängt ist, aber einfach keine Größe liefert.

Warum wird onDraw() nicht aufgerufen?
 
Wird es denn angezeigt?

Wenn das System die View nicht am Screen anzeigen muss, dann wird's auch nicht gezeichnet. Kann es überhaupt am Screen erscheinen bei deiner Konfiguration?
 
Das Problem ist, dass es NICHT erscheint. Deshalb wird auch kein onDraw aufgerufen. Und solange kein onDraw aufgerufen wird, so lang kenn ich die Breites des Frames nicht, und solange kann ich kein Image korrekt erstellen. (Auch ein "vorläufiges" statisches Erstellen eines Bildes mit fixer Breite - die sicher Platz hat - funktioniert nicht.)

Das CustomView mit dynamischem Bild erscheint korrekt bei: (PseudoCode)
scrollView.addView(frameLayout);
frameLayout.addView(customView);

Es erscheint auch korrekt bei statischer Programmierung: (XML)
<scrollView ...>
<tableRow ...>
<frameLayout ...>
<customView ...>

Es erscheint aber gar NICHT (und deshalb auch kein onDraw):
scrollView.addView(tableRow);
tableRow.addView(frameLayout);
frameLayout.addView(customView);

Obwohl bei allen Varianten ein rekursives getChildAt() den richtigen/gewünschten Aufbau der Layouts bestätigt.
 
Zuletzt bearbeitet:
Mich wundert eher dass es beim XML erscheint als das es im Java-Code nicht erscheint.

Aus der Doku von TableRow:
A layout that arranges its children horizontally. A TableRow should always be used as a child of a TableLayout. If a TableRow's parent is not a TableLayout, the TableRow will behave as an horizontal LinearLayout.

Kann es sein, dass deine TableRow das FrameLayout aus dem Viewport hinausschiebt weil noch andere Elemente enthalten sind? Warum verwendest du überhaupt ein TableRow?
 
Meine bisherige Konstellation ist: ScreenBreite (ohne Padding 480)
[XML]ScrollView
TableRow
TextView | EdixText | TextView // Gesamtbreite ca 150
frameLayout
ImageView + ImageView //=CustomView
[/XML]

Ich hätte aber gerne das CustomView neben dem 2. TextView, weil (wenn) genügend Platz ist:
[XML]
ScrollView
TableRow
TextView | EdixText | TextView | frameLayout
ImageView + ImageView //=CustomView
[/XML]

"Rausgeschoben" kann irgendwie nicht sein.
Wie gesagt, bei statischer Programmierung passt's,
bei dynamischer passen zwar die Daten, aber es erscheint nichts.

ABer ich werd mal testen, obs am (fehlende) tableLayout liegt.
 
An deiner Stelle würde ich mir noch einmal genau überlegen was du machen möchtest und noch einmal beim Aufbau deiner View-Hierarchie anfangen.

Das wirkt zurzeit wirr und vor allem nicht auf verschiedene Breiten angepasst.
 
So, nun hab ich es auch mit TableRow getestet: Kein Unterschied.
Am meisten stört mich, dass dass 2. TextView an Stelle 143 erscheint und 40 breit ist, das darauffolgende FramLayout aber an Stelle 0 beginnt, und 0 breit ist
(134 und 117 ist y am Bildschirm)
HTML:
1--class android.widget.TextView    'eh_h'   = 143+40/134   : 0
1--class android.widget.FrameLayout 'fr_h'   = 0+0/117   : 0
Legend:
RekursionsEbene: 1--
ViewClasse: class android.widget.FrameLayout
ViewTag: 'fr_h'
Koorinaten (x+breite/y): 143+40/134
Sichtbarkeit: 0 (=normal)


Hier mein komplettes selbst erzeugtes Layout-Protokoll:
HTML:
class android.widget.TableRow 'null'   = 0+480/76   : 0
class android.widget.TextView 'hd_'   = 0+480/76   : 0
class android.widget.TableRow 'tr_h'   = 0+480/117   : 0
1--class android.widget.TextView     'lb_h'   = 0+50/134   : 0
1--class android.widget.EditText     'h'      = 50+93/117   : 0
1--class android.widget.TextView     'eh_h'   = 143+40/134   : 0
1--class android.widget.FrameLayout  'fr_h'   = 0+0/117   : 0
1--2--class at.TyE.MyLib.SmartBar    'sb_h'   = 0+0/117   : 0
1--2--class android.widget.ImageView 'pf_h'   = 0+0/117   : 0
class android.widget.TableRow 'tr_t'   = 0+480/189   : 0
1--class android.widget.TextView     'lb_t'   = 0+50/206   : 0
1--class android.widget.EditText     't'      = 50+93/189   : 0
1--class android.widget.TextView     'eh_t'   = 143+40/206   : 0
1--class android.widget.FrameLayout  'fr_t'   = 0+0/189   : 0
1--2--class at.TyE.MyLib.SmartBar    'sb_t'   = 0+0/189   : 0
1--2--class android.widget.ImageView 'pf_t'   = 0+0/189   : 0
class android.widget.TableRow 'img_formel'   = 0+480/261   : 0
class android.widget.ImageView 'null'   = 0+128/261   : 0
 
Was genau möchtest du denn überhaupt erreichen? Mal mal ein kleines Bild in Paint oder so und ich schreib mal auf wie ich das machen würde.
 
An deiner Stelle würde ich mir noch einmal genau überlegen was du machen möchtest und noch einmal beim Aufbau deiner View-Hierarchie anfangen.

Das wirkt zurzeit wirr und vor allem nicht auf verschiedene Breiten angepasst.

Du hast recht, auf verschiedene Breite oder mehr Sprachen, ... Soweit bin ich noch nicht.

Aber der Aufbau ist meiner Meinung nach recht simpel,
und soll erst mal stabil laufen, bevor ich mich um andere Formate kümmere.

SmartBar.png


Diese Balken sollen neben den TextViews erscheinen.
 
Das würde ich mit einem geschachtelten LinearLayout lösen.

[xml]
<LinearLayout
android:width="fill_parent"
android:height="wrap_content"
android😱rientation="vertical">
<LinearLayout
android:width="fill_parent"
android:height="wrap_content"
android😱rientation="horizontal">
<TextView
android:width="wrap_content"
android:height="wrap_content"
<!-- sonstige Properties für Höhe --> />
<EditText
android:width="40sp"
android:height="wrap_content"
<!-- sonstige Properties für Höhe-EditBox --> />
<TextView
android:width="wrap_content"
android:height="wrap_content"
android:text="m"
<!-- sonstige Properties für Höhe --> />
<dein.packagename.CustomView
android:width="fill_parent"
android:height="wrap_content"
<!-- sonstige properties -->
</LinearLayout>

<LinearLayout
android:width="fill_parent"
android:height="wrap_content"
android😱rientation="horizontal">
<TextView
android:width="wrap_content"
android:height="wrap_content"
<!-- sonstige Properties für Zeit --> />
<EditText
android:width="40sp"
android:height="wrap_content"
<!-- sonstige Properties für Zeit-EditBox --> />
<TextView
android:width="wrap_content"
android:height="wrap_content"
android:text="sec"
<!-- sonstige Properties für Zeit --> />
<dein.packagename.CustomView
android:width="fill_parent"
android:height="wrap_content"
<!-- sonstige properties -->
</LinearLayout>
</LinearLayout>
[/xml]

Darum kannst du dann noch eine ScrollView packen wenn du das brauchst. Alternativ, wenn die Activity noch viele andere Views enthalten soll, kann man das auch mit einem RelativeLayout abbilden, das ist etwas performanter.

Das XML ist ungetestet aber ich glaub du bekommst eine Idee wie's zu machen ist.
 
Mein CustomView verlangt ein FrameLayout, weil ich darin 2 Bilder überlagere.
Aber das kann (sollte) ich ja auch intern selbst erzeugen.
(Darf eigentlich nicht sein, dass meine Activity sich nach dem CustomView richten muss.)

So gesehen hat mich dein Tipp "ich soll's nochmal durchschauen" sehr viel weitergebracht.

Kann ich aber erst abends testen.

PS: Ungetestetes XML: ich muss es so oder so dynamisch machen, weil es deutlich mehr Zeilen, und deutlich komplexer werden kann. Aber die Idee gefällt mir gut. Irgendwie hat sich das tablerow eh exotisch angefühlt.

(PPS: Aber trotzdem ist mir unerklärlich, warum mein FrameLayout ganz links klebt (statt nach dem TextView), und gar nicht angezeigt wird?!? Ich hoffe, dass sich das mit LinearLayout dann anders verhält.)
 
Aber das kann (sollte) ich ja auch intern selbst erzeugen.
(Darf eigentlich nicht sein, dass meine Activity sich nach dem CustomView richten muss.)
Gut erkannt ;-)

Das FrameLayout ist sowieso ein sehr biestiges View mit dem es generell mehr Probleme als Lösungen gibt. Ich geh dem aus dem Weg so gut es geht und verwende es nur bei Tabs.
 
Übrigens: der nächste Schritt (wenn's dann funktioniert), ist in der Tat andere Formate, Landscape, ... (und auch andere Sprachen) zu ermöglichen.

Kennst du da ein einfaches Einführungs-Tutorial?
Offensichtlich bist du ja wirklich Andorid-Profi.
 
Google bemüht sich da eh sehr, ich würde für Lokalisierung dazu greifen.

Punkto Landscape-Change: Das ist absolut keine Hexerei. Es gibt zwei Möglichkeiten damit umzugehen: Entweder das System regelt das, dann wird beim Umschalten zwischen den Ausrichtungen immer onCreate ausgeführt und eine neue View erstellt. Wenn deine content-view damit zurecht kommt bist du schon fertig. (Allerdings böse wenn du asynchrone Tasks laufen hast, die da möglicherweise eine View updaten wollen die's nimmer gibt)
Deswegen gibt's auch die zweite Möglichkeit selbst damit um zu gehen, da gibt's auch von Google ein Tutorial (letzter Punkt) dazu.
 
So, kurzes Feedback:
Ich habe jetzt testhalber einfach NUR alle TableRow gegen LinearLayout (horizontal) getauscht und schon funktioniert es!

(Jetzt kommt natürlich noch meine Bereinigung des internen FrameLayout, ... aber das hat nichts mit der Funktion zu tun.)

Als Erklärung, warum's nicht funktioniert hat, akzeptiere ich mal, dass TableRow ohne TableView nicht gedacht ist, (obwohl dieser Versuch ja auch nichts gebracht hatte).
Aber was soll's.

Vielen Dank für deine Hilfe(n).
 

Zurück
Oben