Ich habe eine Ansicht bestehend aus TableLayout, TableRow and TextView
. Ich möchte, dass es wie ein Gitter aussieht. Ich muss die Höhe und Breite dieses Gitters ermitteln. Die Methoden getHeight()
und getWidth()
Rückkehr immer 0. Dies geschieht , wenn ich das Netz dynamisch formatieren und auch wenn ich eine XML - Version verwenden.
Wie rufe ich die Dimensionen für eine Ansicht ab?
Hier ist mein Testprogramm, mit dem ich in Debug die Ergebnisse überprüft habe:
import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TextView;
public class appwig extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maindemo); //<- includes the grid called "board"
int vh = 0;
int vw = 0;
//Test-1 used the xml layout (which is displayed on the screen):
TableLayout tl = (TableLayout) findViewById(R.id.board);
tl = (TableLayout) findViewById(R.id.board);
vh = tl.getHeight(); //<- getHeight returned 0, Why?
vw = tl.getWidth(); //<- getWidth returned 0, Why?
//Test-2 used a simple dynamically generated view:
TextView tv = new TextView(this);
tv.setHeight(20);
tv.setWidth(20);
vh = tv.getHeight(); //<- getHeight returned 0, Why?
vw = tv.getWidth(); //<- getWidth returned 0, Why?
} //eof method
} //eof class
getHeight()
undgetWidth()
nachdem der Aktivitätslebenszyklus die Ansichten gebeten hat, sich selbst zu messen, mit anderen Worten, machen Sie solche DingeonResume()
und das war's. Sie sollten nicht erwarten, dass ein noch nicht angelegtes Objekt seine Dimensionen kennt, das ist der ganze Trick. Keine Notwendigkeit für die unten vorgeschlagene Magie.getHeight()/Width()
inonResume()
brachte nicht> 0 Wert für mich.Antworten:
Ich glaube, das OP ist längst vorbei, aber falls diese Antwort zukünftigen Suchenden helfen kann, dachte ich, ich würde eine Lösung veröffentlichen, die ich gefunden habe. Ich habe diesen Code zu meiner
onCreate()
Methode hinzugefügt :BEARBEITET: 07/05/11, um Code aus Kommentaren aufzunehmen:
Zuerst bekomme ich einen endgültigen Verweis auf meine
TextView
(um in deronGlobalLayout()
Methode zuzugreifen ). Als nächstes erhalte ich dasViewTreeObserver
von meinemTextView
und füge einOnGlobalLayoutListener
Überschreiben hinzuonGLobalLayout
(es scheint hier keine Methode der Oberklasse zu geben ...) und füge meinen Code hinzu, der die Kenntnis der Maße der Ansicht in diesen Listener erfordert. Alles funktioniert wie erwartet für mich, also hoffe ich, dass dies helfen kann.quelle
tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
diese Weise sollte der Listener nach dem ersten Mal entfernt werden es passiert.addOnLayoutChangeListener
funktioniert auch! :)Ich füge nur eine alternative Lösung hinzu, überschreibe die onWindowFocusChanged-Methode Ihrer Aktivität und Sie können die Werte von getHeight (), getWidth () von dort abrufen.
quelle
ViewTreeObserver
.Sie versuchen, die Breite und Höhe eines Elements zu ermitteln, das noch nicht gezeichnet wurde.
Wenn Sie Debug verwenden und irgendwann anhalten, werden Sie feststellen, dass der Bildschirm Ihres Geräts noch leer ist. Dies liegt daran, dass Ihre Elemente noch nicht gezeichnet wurden, sodass Sie die Breite und Höhe von etwas noch nicht ermitteln können, was noch nicht der Fall ist existieren.
Und ich könnte mich irren, werde aber
setWidth()
nicht immer respektiert,Layout
legt seine Kinder fest und entscheidet, wie sie gemessen werden (Aufrufchild.measure()
). Wenn Sie also festlegensetWidth()
, wird nicht garantiert, dass Sie diese Breite erhalten, nachdem das Element gezeichnet wurde.Was Sie brauchen, ist,
getMeasuredWidth()
(das neueste Maß Ihrer Ansicht) irgendwo zu verwenden, nachdem die Ansicht tatsächlich gezeichnet wurde.Schauen Sie in den
Activity
Lebenszyklus, um den besten Moment zu finden.http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Ich glaube, eine gute Praxis ist es, Folgendes zu verwenden
OnGlobalLayoutListener
:Sie können diesen Code direkt in platzieren
onCreate()
und er wird aufgerufen, wenn Ansichten angelegt werden.quelle
Verwenden Sie die Post-Methode der Ansicht wie folgt
quelle
Ich habe versucht,
onGlobalLayout()
eine benutzerdefinierte Formatierung von aTextView
vorzunehmen, aber wie @George Bailey bemerkte,onGlobalLayout()
wird sie tatsächlich zweimal aufgerufen: einmal auf dem anfänglichen Layoutpfad und ein zweites Mal nach dem Ändern des Textes.View.onSizeChanged()
funktioniert bei mir besser, denn wenn ich den Text dort ändere, wird die Methode nur einmal aufgerufen (während des Layoutdurchlaufs). Dies erforderte eine Unterklassifizierung vonTextView
, kann jedoch auf API-Ebene 11+View. addOnLayoutChangeListener()
verwendet werden, um eine Unterklassifizierung zu vermeiden.Eine weitere Sache, um die richtige Breite der Ansicht zu erhalten
View.onSizeChanged()
,layout_width
sollte auf gesetzt werdenmatch_parent
, nichtwrap_content
.quelle
Versuchen Sie, Größen in einem Konstruktor oder einer anderen Methode abzurufen, die ausgeführt wird, bevor Sie das tatsächliche Bild erhalten?
Sie erhalten keine Abmessungen, bevor alle Komponenten tatsächlich gemessen wurden (da Ihre XML-Datei nichts über Ihre Anzeigegröße, die Positionen der Eltern und was auch immer weiß).
Versuchen Sie, Werte nach onSizeChanged () abzurufen (obwohl dies mit Null aufgerufen werden kann), oder warten Sie einfach, bis Sie ein tatsächliches Bild erhalten.
quelle
Wie bereits erwähnt, können Sie eine
OnLayoutChangeListener
Ansicht verwenden, die Sie selbst verfolgen möchtenSie können den Listener im Rückruf entfernen, wenn Sie nur das ursprüngliche Layout möchten.
quelle
Ich denke, das ist es, worauf Sie achten müssen: Verwendung
onSizeChanged()
Ihrer Ansicht. Hier ist ein erweiterter Code - Schnipsel, wie zu verwenden ,onSizeChanged()
das Layout des oder nach Ansicht der Höhe und Breite dynamisch zu bekommen http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.htmlquelle
ViewTreeObserver
undonWindowFocusChanged()
sind überhaupt nicht so notwendig.Wenn Sie das
TextView
as-Layout aufblasen und / oder Inhalte einfügen und festlegenLayoutParams
, können SiegetMeasuredHeight()
und verwendengetMeasuredWidth()
.ABER du musst vorsichtig sein mit
LinearLayouts
(vielleicht auch anderenViewGroups
). Das Problem dabei ist, dass Sie die Breite und Höhe danachonWindowFocusChanged()
abrufen können. Wenn Sie jedoch versuchen, einige Ansichten hinzuzufügen, können Sie diese Informationen erst abrufen, wenn alles gezeichnet wurde. Ich habe versucht , mehr hinzufügenTextViews
zuLinearLayouts
imitieren eineFlowLayout
(Umbruchart) und konnte so nicht verwendenListeners
. Sobald der Prozess gestartet ist, sollte er synchron fortgesetzt werden. In diesem Fall möchten Sie möglicherweise die Breite in einer Variablen behalten, um sie später verwenden zu können, da Sie sie möglicherweise beim Hinzufügen von Ansichten zum Layout benötigen.quelle
Obwohl die vorgeschlagene Lösung funktioniert, ist sie möglicherweise nicht für jeden Fall die beste Lösung, da sie auf der Dokumentation für basiert
ViewTreeObserver.OnGlobalLayoutListener
Das heißt, es wird oft aufgerufen und nicht immer wird die Ansicht gemessen (Höhe und Breite werden bestimmt).
Eine Alternative ist die Verwendung,
ViewTreeObserver.OnPreDrawListener
die nur aufgerufen wird, wenn die Ansicht zum Zeichnen bereit ist und alle ihre Maße hat.quelle
Sie sollten sich lieber den View-Lebenszyklus ansehen: http://developer.android.com/reference/android/view/View.html Im Allgemeinen sollten Sie Breite und Höhe erst dann genau kennen, wenn Ihre Aktivität den Status onResume erreicht hat.
quelle
Sie können eine Sendung verwenden, die in OnResume () aufgerufen wird.
Beispielsweise:
Sie können die Höhe einer Ansicht in OnCreate (), onStart () oder sogar in onResume () nicht abrufen, da kcoppock geantwortet hat
quelle
Höhe und Breite sind Null, da die Ansicht zum Zeitpunkt der Anforderung von Höhe und Breite noch nicht erstellt wurde. Eine einfachste Lösung ist
Diese Methode ist im Vergleich zu anderen Methoden gut, da sie kurz und knackig ist.
quelle
Einfache Antwort: Dies funktionierte bei mir ohne Probleme. Es scheint, dass der Schlüssel darin besteht, sicherzustellen, dass die Ansicht den Fokus hat, bevor Sie getHeight usw. verwenden. Verwenden Sie dazu die Methode hasFocus () und dann die Methode getHeight () in dieser Reihenfolge. Nur 3 Codezeilen erforderlich.
ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1);
myImageButton1.hasFocus();
int myButtonHeight = myImageButton1.getHeight();
Log.d("Button Height: ", ""+myButtonHeight );//Not required
Ich hoffe es hilft.
quelle
Verwenden Sie getMeasuredWidth () und getMeasuredHeight () für Ihre Ansicht.
Entwicklerhandbuch: Anzeigen
quelle
KORREKTUR: Ich habe herausgefunden, dass die obige Lösung schrecklich ist. Besonders wenn Ihr Telefon langsam ist. Und hier habe ich eine andere Lösung gefunden: Berechnen Sie den px-Wert des Elements, einschließlich der Ränder und Auffüllungen: dp bis px: https://stackoverflow.com/a/6327095/1982712
oder dimension.xml bis px: https://stackoverflow.com/a/16276351/1982712
sp to px: https://stackoverflow.com/a/9219417/1982712 (Lösung umkehren)
oder dimension to px: https://stackoverflow.com/a/16276351/1982712
und das ist es.
quelle