Das Grundproblem besteht darin, dass Sie auf die Zeichnungsphase für die tatsächlichen Messungen warten müssen (insbesondere bei dynamischen Werten wie wrap_content
oder match_parent
), diese Phase jedoch normalerweise noch nicht abgeschlossen ist onResume()
. Sie benötigen also eine Problemumgehung, um auf diese Phase zu warten. Hierfür gibt es verschiedene mögliche Lösungen:
1. Hören Sie sich Zeichen- / Layoutereignisse an: ViewTreeObserver
Ein ViewTreeObserver wird für verschiedene Zeichenereignisse ausgelöst. Normalerweise OnGlobalLayoutListener
ist dies das, was Sie möchten, um die Messung zu erhalten, sodass der Code im Listener nach der Layoutphase aufgerufen wird, damit die Messungen fertig sind:
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
view.getHeight(); //height is ready
}
});
Hinweis: Der Listener wird sofort entfernt, da er sonst bei jedem Layoutereignis ausgelöst wird. Wenn Sie Apps SDK Lvl <16 unterstützen müssen, verwenden Sie diese Option, um die Registrierung des Listeners aufzuheben :
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. Fügen Sie der Layout-Warteschlange eine ausführbare Datei hinzu: View.post ()
Nicht sehr bekannt und meine Lieblingslösung. Verwenden Sie einfach die Post-Methode der Ansicht mit Ihrer eigenen ausführbaren Datei. Dies stellt Ihren Code im Grunde genommen nach dem Maß, dem Layout usw. der Ansicht in die Warteschlange , wie von Romain Guy angegeben :
Die UI-Ereigniswarteschlange verarbeitet Ereignisse der Reihe nach. Nachdem setContentView () aufgerufen wurde, enthält die Ereigniswarteschlange eine Nachricht, in der nach einem Relayout gefragt wird. Alles, was Sie in die Warteschlange stellen, geschieht also nach dem Layout-Durchlauf
Beispiel:
final View view=//smth;
...
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
}
});
Der Vorteil gegenüber ViewTreeObserver
:
- Ihr Code wird nur einmal ausgeführt und Sie müssen den Observer nach der Ausführung nicht deaktivieren, was problematisch sein kann
- weniger ausführliche Syntax
Verweise:
3. Überschreiben Sie die onLayout-Methode von Views
Dies ist nur in bestimmten Situationen praktisch, wenn die Logik in der Ansicht selbst gekapselt werden kann, andernfalls ist dies eine recht ausführliche und umständliche Syntax.
view = new View(this) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
view.getHeight(); //height is ready
}
};
Beachten Sie auch, dass onLayout viele Male aufgerufen wird. Überlegen Sie also, was Sie in der Methode tun, oder deaktivieren Sie Ihren Code nach dem ersten Mal
4. Überprüfen Sie, ob die Layoutphase durchlaufen wurde
Wenn Sie Code haben, der beim Erstellen der Benutzeroberfläche mehrmals ausgeführt wird, können Sie die folgende Support-Methode v4 lib verwenden:
View viewYouNeedHeightFrom = ...
...
if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) {
viewYouNeedHeightFrom.getHeight();
}
Gibt true zurück, wenn die Ansicht mindestens ein Layout durchlaufen hat, seit sie zuletzt an ein Fenster angehängt oder von diesem getrennt wurde.
Zusätzlich: Statisch definierte Messungen erhalten
Wenn es ausreicht, nur die statisch definierte Höhe / Breite zu erhalten, können Sie dies einfach tun mit:
Beachten Sie jedoch, dass dies nach dem Zeichnen möglicherweise von der tatsächlichen Breite / Höhe abweicht. Der Javadoc beschreibt den Unterschied perfekt:
Die Größe einer Ansicht wird mit einer Breite und einer Höhe ausgedrückt. Eine Ansicht besitzt tatsächlich zwei Paare von Breiten- und Höhenwerten.
Das erste Paar ist als gemessene Breite und gemessene Höhe bekannt. Diese Dimensionen definieren, wie groß eine Ansicht in ihrem übergeordneten Element sein soll (weitere Informationen finden Sie unter Layout). Die gemessenen Dimensionen können durch Aufrufen von getMeasuredWidth () und getMeasuredHeight () abgerufen werden.
Das zweite Paar ist einfach als Breite und Höhe oder manchmal als Zeichenbreite und Zeichenhöhe bekannt. Diese Abmessungen definieren die tatsächliche Größe der Ansicht auf dem Bildschirm, zum Zeitpunkt des Zeichnens und nach dem Layout. Diese Werte können, müssen aber nicht von der gemessenen Breite und Höhe abweichen. Die Breite und Höhe können durch Aufrufen von getWidth () und getHeight () ermittelt werden.