GetWidth () und getHeight () von View geben 0 zurück

513

Ich erstelle alle Elemente in meinem Android-Projekt dynamisch. Ich versuche, die Breite und Höhe eines Knopfes zu ermitteln, damit ich diesen Knopf drehen kann. Ich versuche nur zu lernen, wie man mit der Android-Sprache arbeitet. Es wird jedoch 0 zurückgegeben.

Ich habe einige Nachforschungen angestellt und festgestellt, dass dies an einem anderen Ort als in der onCreate()Methode erfolgen muss. Wenn mir jemand ein Beispiel geben kann, wie es geht, wäre das großartig.

Hier ist mein aktueller Code:

package com.animation;

import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;

public class AnimateScreen extends Activity {


//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout ll = new LinearLayout(this);

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(30, 20, 30, 0);

    Button bt = new Button(this);
    bt.setText(String.valueOf(bt.getWidth()));

    RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
    ra.setDuration(3000L);
    ra.setRepeatMode(Animation.RESTART);
    ra.setRepeatCount(Animation.INFINITE);
    ra.setInterpolator(new LinearInterpolator());

    bt.startAnimation(ra);

    ll.addView(bt,layoutParams);

    setContentView(ll);
}

Jede Hilfe wird geschätzt.

ngreenwood6
quelle

Antworten:

197

Sie rufen getWidth()zu früh an. Die Benutzeroberfläche wurde noch nicht dimensioniert und auf dem Bildschirm angezeigt.

Ich bezweifle, dass Sie sowieso das tun möchten, was Sie tun - animierte Widgets ändern ihre anklickbaren Bereiche nicht, sodass die Schaltfläche weiterhin auf Klicks in der ursprünglichen Ausrichtung reagiert, unabhängig davon, wie sie sich gedreht hat.

Abgesehen davon können Sie eine Dimensionsressource verwenden , um die Schaltflächengröße zu definieren, und dann auf diese Dimensionsressource aus Ihrer Layoutdatei und Ihrem Quellcode verweisen, um dieses Problem zu vermeiden.

CommonsWare
quelle
82
ngreenwood6, was ist deine andere Lösung?
Andrew
12
@Andrew - Wenn Sie möchten, dass negreenwood6 über Ihr Follow-up informiert wird, müssen Sie Ihre Nachricht wie ich an Sie senden (ich denke, die ersten drei Buchstaben reichen aus) - CommonsWare wird automatisch benachrichtigt, da er diese Antwort geschrieben hat, ngreen jedoch nicht es sei denn, Sie sprechen sie an.
Peter Ajtai
11
@Override public void onWindowFocusChanged (boolescher hasFocus) {// TODO Automatisch generierte Methode stub super.onWindowFocusChanged (hasFocus); // Hier kannst du die Größe bekommen! }
Sana
5
@ ngreenwood6 Was war deine Lösung?
Nima Vaziri
5
Verwenden Sie diesen Listener, um die Größe zu ermitteln, wenn Ihr Bildschirm bereit ist. view.getViewTreeObserver (). addOnGlobalLayoutListener (neuer ViewTreeObserver.OnGlobalLayoutListener () {}
Sinan Dizdarević
815

Das Grundproblem besteht darin, dass Sie auf die Zeichnungsphase für die tatsächlichen Messungen warten müssen (insbesondere bei dynamischen Werten wie wrap_contentoder 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 OnGlobalLayoutListenerist 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.

Patrick Favre
quelle
1
Ich verwende den view.post in einem Fragment. Ich muss die Ansicht messen, deren Elterngröße 0 dp beträgt und für die ein Gewicht festgelegt ist. Alles, was ich versuche, gibt eine Höhe von Null zurück (ich habe auch den globalen Layout-Listener ausprobiert). Wenn ich den view.post-Code mit einer Verzögerung von 125 in onViewCreated einfüge, funktioniert er, aber nicht ohne Verzögerung. Ideen?
Psest328
6
Schade, dass man eine Antwort nur einmal positiv bewerten kann, wirklich gute Erklärung. Ich hatte ein Problem mit einer Ansichtsrotation, wenn ich meine App beendet und von den letzten Apps aus neu gestartet habe. Wenn ich es von dort wischte und einen Neustart durchführte, war alles in Ordnung. Die view.post () hat mir den Tag gerettet!
Matthias
1
Vielen Dank. Normalerweise verwende ich View.post () (2. Methode), aber wenn es von einem Hintergrund-Thread aufgerufen wird, funktioniert es manchmal nicht. Also vergiss nicht zu schreiben runOnUiThread(new Runnable() {...}. Derzeit verwende ich eine Variation der 1. Methode : addOnLayoutChangeListener. Vergessen Sie nicht, es dann im Inneren zu entfernen: removeOnLayoutChangeListener. Es funktioniert auch vom Hintergrund-Thread.
CoolMind
2
Leider funktioniert 'View.post ()' nicht immer. Ich habe 2 Projekte, die sehr ähnlich sind. In einem Projekt funktioniert es, in dem anderen nicht. :(. In beiden Situationen rufe ich die Methode von 'onCreate ()' Methode aus einer Aktivität auf. Irgendein Vorschlag warum?
Adrian Buciuman
1
Ich finde das Problem. In einem Projekt hat die Ansicht android:visibility="gone", und in dem anderen Projekt war die Sichtbarkeitseigenschaft invisible. Wenn die Sichtbarkeit ist, wird gonedie Breite immer 0 sein.
Adrian Buciuman
262

Wir können benutzen

@Override
 public void onWindowFocusChanged(boolean hasFocus) {
  super.onWindowFocusChanged(hasFocus);
  //Here you can get the size!
 }
Sana
quelle
10
Wie können wir also in Fragmenten arbeiten? funktioniert das nur in Aktivität?
Olkunmustafa
8
Dies sollte die Sache tun, aber es sollte nicht die Antwort sein. Ein Benutzer möchte zu jedem Zeitpunkt Dimensionen erhalten, anstatt auf dem Fenster gezeichnet zu werden. Diese Methode wird auch mehrmals aufgerufen oder jedes Mal, wenn im Fenster eine Änderung (Ansicht ausblenden, weg, Hinzufügen neuer Ansichten usw.) vorgenommen wird. Also benutze es vorsichtig :)
Dr. aNdRO
1
Dies ist ein Hack und es scheint, als wäre die Verwendung des ViewTreeObservers besser.
i_am_jorf
Das soll nicht unhöflich klingen, aber das Hinterlassen eines automatisch generierten Kommentars (insbesondere in 2 Codezeilen) gibt nicht viel Vertrauen, dass Sie tatsächlich wissen, was Sie tun.
Natix
Leider hat es bei mir nicht funktioniert. Der Versuch mit viewTreeObserver hat bei mir funktioniert.
Narendra Singh
109

Ich habe diese Lösung verwendet, die meiner Meinung nach besser ist als onWindowFocusChanged (). Wenn Sie ein DialogFragment öffnen und dann das Telefon drehen, wird onWindowFocusChanged nur aufgerufen, wenn der Benutzer den Dialog schließt.

    yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            // Ensure you call it only once :
            yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

            // Here you can get the size :)
        }
    });

Bearbeiten: Da removeGlobalOnLayoutListener veraltet ist, sollten Sie jetzt Folgendes tun:

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {

    // Ensure you call it only once :
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
    else {
        yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    // Here you can get the size :)
}
Tim Autin
quelle
4
Dies ist bei weitem die beste Lösung! weil es auch bei dynamischen Lösungen funktioniert, bei denen Breite und Höhe nicht bekannt und berechnet sind. dh in einem relativen Layout basierend auf den Positionen / Größen anderer Elemente. Gut gemacht!
George Pligoropoulos
2
Dies erfordert API 16 oder höher (Jelly Bean)
Tomsv
7
API 16 IST NICHT ERFORDERLICH! Das einzige Problem ist die Methode removeGlobalOnLayoutListener, die von API 16 veraltet ist. Es gibt jedoch eine einfache Lösung, die mit allen API-Ebenen kompatibel ist - stackoverflow.com/questions/16189525/…
gingo
Wenn Sie den Listener entfernen müssen, damit er sich nicht oft aufruft und Probleme mit verschiedenen APIs haben, empfehle ich Ihnen, am Anfang der Klasse einen falschen Booleschen Wert festzulegen und ihn nach dem Erfassen der Werte auf true zu setzen Die Werte werden nicht erneut erfasst.
Mansour Fahad
Wenn Sie den Listener nach dem ersten Durchlauf entfernen, erhalten Sie möglicherweise falsche Abmessungen: 02-14 10: 18: 53.786 15063-15063 / PuzzleFragment: Höhe: 1647 Breite: 996 02-14 10: 18: 53.985 15063-15063 / PuzzleFragment: Höhe : 1500 Breite: 996
Leos Literak
76

Wie Ian in diesem Thread für Android-Entwickler feststellt :

Der Deal ist jedenfalls, dass das Layout des Inhalts eines Fensters danach erfolgt alle Elemente erstellt und ihren übergeordneten Ansichten hinzugefügt wurden. Dies muss so sein, denn bis Sie wissen, welche Komponenten eine Ansicht enthält und was sie enthalten usw., können Sie sie nicht sinnvoll gestalten.

Fazit: Wenn Sie getWidth () usw. in einem Konstruktor aufrufen, wird Null zurückgegeben. Das Verfahren besteht darin, alle Ihre Ansichtselemente im Konstruktor zu erstellen und dann auf den Aufruf der onSizeChanged () -Methode Ihrer Ansicht zu warten. Dann ermitteln Sie zuerst Ihre tatsächliche Größe, und legen dann die Größen Ihrer GUI-Elemente fest.

Beachten Sie auch, dass onSizeChanged () manchmal mit den Parametern Null aufgerufen wird. Überprüfen Sie diesen Fall und kehren Sie sofort zurück (damit Sie bei der Berechnung Ihres Layouts usw. keine Division durch Null erhalten). Einige Zeit später wird es mit den realen Werten aufgerufen.

kerem yokuva
quelle
8
onSizeChanged hat bei mir funktioniert. onWindowFocusedChanged wird in meiner benutzerdefinierten Ansicht nicht aufgerufen.
Aaronmarino
Das sieht nach einer guten Lösung aus, aber was sollte ich immer in meiner benutzerdefinierten Ansicht erstellen, um die onSizeChanged-Methode zu überschreiben?
M. ElSaka
Bottom line, if you call getWidth() etc. in a constructor, it will return zero.Das ist ein Bingo. Die Wurzel meiner Probleme.
MikeNereson
Ich schlage diese Lösung für Fragmente vor, da einige andere Lösungen in meinem Fall 0 zurückgeben.
WindRider
66

Wenn Sie die Breite eines Widgets abrufen müssen, bevor es auf dem Bildschirm angezeigt wird, können Sie getMeasuredWidth () oder getMeasuredHeight () verwenden.

myImage.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int width = myImage.getMeasuredWidth();
int height = myImage.getMeasuredHeight();
sulu.dev
quelle
5
Aus irgendeinem Grund war dies die einzige Antwort, die für mich funktioniert hat - danke!
Farbod Salamat-Zadeh
Das gleiche für mich, die einfachste Lösung, die für mich funktioniert hat
Tima
Arbeite wie ein Zauber!
Morales Batovski
1
@CommonsWare Wie gibt diese Lösung die Höhe und Breite vor dem View Tree Observer beim Rückruf globaler Layouts an? Eine Erklärung wäre hilfreich.
Mightian
22

Ich würde lieber OnPreDrawListener()statt verwenden addOnGlobalLayoutListener(), da es etwas früher als andere Hörer aufgerufen wird.

    view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
    {
        @Override
        public boolean onPreDraw()
        {
            if (view.getViewTreeObserver().isAlive())
                view.getViewTreeObserver().removeOnPreDrawListener(this);

            // put your code here
            return true;
        }
    });
Ayaz Alifov
quelle
3
Beachten Sie, dass dies return falsebedeutet , den aktuellen Zeichnungsdurchlauf abzubrechen . Fahren Sie return truestattdessen fort.
Pang
9

Eine Kotlin-Erweiterung, um das globale Layout zu beobachten und eine bestimmte Aufgabe auszuführen, wenn die Höhe dynamisch bereit ist.

Verwendungszweck:

view.height { Log.i("Info", "Here is your height:" + it) }

Implementierung:

fun <T : View> T.height(function: (Int) -> Unit) {
    if (height == 0)
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                function(height)
            }
        })
    else function(height)
}
Renetik
quelle
6

AndroidX verfügt über mehrere Erweiterungsfunktionen, die Sie bei dieser Art von Arbeit unterstützen androidx.core.view

Sie müssen dafür Kotlin verwenden.

Das, was hier am besten passt, ist doOnLayout:

Führt die angegebene Aktion aus, wenn diese Ansicht angelegt ist. Wenn die Ansicht angelegt wurde und kein Layout angefordert wurde, wird die Aktion sofort ausgeführt. Andernfalls wird die Aktion ausgeführt, nachdem die Ansicht das nächste Mal angelegt wurde.

Die Aktion wird beim nächsten Layout nur einmal aufgerufen und dann entfernt.

In Ihrem Beispiel:

bt.doOnLayout {
    val ra = RotateAnimation(0,360,it.width / 2,it.height / 2)
    // more code
}

Abhängigkeit: androidx.core:core-ktx:1.0.0

Vlad
quelle
Dies ist die einzig richtige Antwort. android.googlesource.com/platform/frameworks/support/+/…
hrules6872
1
Diese Erweiterungen sind wirklich wichtig und nützlich
Ahmed
5

Ein Liner, wenn Sie RxJava & RxBindings verwenden . Ähnlicher Ansatz ohne Boilerplate. Dies löst auch den Hack, um Warnungen wie in der Antwort von Tim Autin zu unterdrücken .

RxView.layoutChanges(yourView).take(1)
      .subscribe(aVoid -> {
           // width and height have been calculated here
      });

Das ist es. Sie müssen sich nicht abmelden, auch wenn Sie nie angerufen haben.

Odys
quelle
4

Dies geschieht, weil die Ansicht mehr Zeit benötigt, um aufgeblasen zu werden. Anstatt aufzurufen view.widthund view.heightden Haupt-Thread zu aktivieren, sollten Sie view.post { ... }sicherstellen, dass Ihr Thread viewbereits aufgeblasen ist. In Kotlin:

view.post{width}
view.post{height}

In Java können Sie auch getWidth()und getHeight()Methoden in a aufrufen und Runnabledie Runnableto- view.post()Methode übergeben.

view.post(new Runnable() {
        @Override
        public void run() {
            view.getWidth(); 
            view.getHeight();
        }
    });
Ehsan Nokandi
quelle
Dies ist keine korrekte Antwort, da die Ansicht möglicherweise nicht gemessen und angelegt wird, wenn der veröffentlichte Code ausgeführt wird. Es wäre ein Randfall, .postgarantiert aber nicht, dass die Ansicht angelegt wird.
d.aemon
1
Diese Antwort war großartig und hat für mich funktioniert. Vielen Dank Ehsan
MMG
3

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

view.post(new Runnable() {
        @Override
        public void run() {
            view.getHeight(); //height is ready
            view.getWidth(); //width is ready
        }
    });

Diese Methode ist im Vergleich zu anderen Methoden gut, da sie kurz und knackig ist.

Shivam Yadav
quelle
3

Vielleicht hilft das jemandem:

Erstellen Sie eine Erweiterungsfunktion für die View-Klasse

Dateiname: ViewExt.kt

fun View.afterLayout(what: () -> Unit) {
    if(isLaidOut) {
        what.invoke()
    } else {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                what.invoke()
            }
        })
    }
}

Dies kann dann in jeder Ansicht verwendet werden mit:

view.afterLayout {
    do something with view.height
}
Pepijn
quelle
2

Die Antwort mit postist falsch, da die Größe möglicherweise nicht neu berechnet wird.
Eine weitere wichtige Sache ist, dass die Ansicht und alle Vorfahren sichtbar sein müssen . Dafür benutze ich eine EigenschaftView.isShown .

Hier ist meine Kotlin-Funktion, die irgendwo in Utils platziert werden kann:

fun View.onInitialized(onInit: () -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (isShown) {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                onInit()
            }
        }
    })
}

Und die Verwendung ist:

myView.onInitialized {
    Log.d(TAG, "width is: " + myView.width)
}
pavelperc
quelle
1

Wenn Sie Kotlin verwenden

  leftPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {

            override fun onGlobalLayout() {

                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                    leftPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
                else {
                    leftPanel.viewTreeObserver.removeGlobalOnLayoutListener(this)
                }

                // Here you can get the size :)
                leftThreshold = leftPanel.width
            }
        })
Hitesh Sahu
quelle
0

Gone Views gibt 0 als Höhe zurück, wenn die App im Hintergrund angezeigt wird. Dies ist mein Code (1oo% funktioniert)

fun View.postWithTreeObserver(postJob: (View, Int, Int) -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            val widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            val heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            measure(widthSpec, heightSpec)
            postJob(this@postWithTreeObserver, measuredWidth, measuredHeight)
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                @Suppress("DEPRECATION")
                viewTreeObserver.removeGlobalOnLayoutListener(this)
            } else {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        }
    })
}

quelle
0

Wir müssen warten, bis die Ansicht gezeichnet wird. Verwenden Sie dazu den OnPreDrawListener. Kotlin Beispiel:

val preDrawListener = object : ViewTreeObserver.OnPreDrawListener {

                override fun onPreDraw(): Boolean {
                    view.viewTreeObserver.removeOnPreDrawListener(this)

                    // code which requires view size parameters

                    return true
                }
            }

            view.viewTreeObserver.addOnPreDrawListener(preDrawListener)
Artem Botnev
quelle