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

Ich schaffe alle Elemente in meinem Android-Projekt dynamisch. Ich versuche, die Breite und die Höhe eines Knopfes zu bekommen, damit ich diesen Knopf umdrehen kann. Ich versuche nur zu lernen, wie man mit der android-Sprache arbeitet. Allerdings gibt es 0 zurück.

Ich habe einige Recherchen gemacht und ich habe gesehen, dass es irgendwo anders als in der onCreate() Methode getan werden muss. Wenn jemand mir ein Beispiel dafür geben kann, wie es geht, wäre das toll.

  • Automatisierte GUI-Test-Framework für Android
  • Wie man Fehler in Bitmap-Größe zu beheben überschreitet VM-Budget
  • Dynamisches Einfügen von String in ein String-Array in Android
  • Schlechte Leistung beim kontinuierlichen Zeichnen in CustomView
  • Testen von Android-Projekt mit Jar Dependecies
  • ActionBar mit Navigations-Tabs ändert die Höhe mit der Bildschirmausrichtung
  • 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.

  • Android - zeige eine unbestimmte Fortschrittsanzeige ohne den Dialog
  • NullPointerException beim Aufruf von getSupportActionBar () aus dem Inneren von Fragment (ActionBarCompat)
  • Verwenden von WebView setHttpAuthUsernamePassword?
  • EditText unterstreichen unterhalb der Texteigenschaft
  • Wie lade ich (gezwungen, wenn nötig) 9-Patch (NinePatchDrawable) aus dem Speicher in Android?
  • Navigationsschublade - Deaktivieren Sie Klick auf Artikel hinter der Schublade
  • 7 Solutions collect form web for “GetWidth () und getHeight () von View gibt 0 zurück”

    Sie rufen getWidth() zu früh auf. Die UI wurde noch nicht bemessen und auf dem Bildschirm angelegt.

    Ich bezweifle, dass du tun möchtest, was du tust, trotzdem – Widgets, die animiert werden, ändern ihre anpassbaren Bereiche nicht, und so reagiert der Button immer noch auf Klicks in der ursprünglichen Ausrichtung, unabhängig davon, wie er sich gedreht hat.

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

    Das Grundproblem ist, dass man auf die Zeichnungsphase für die eigentlichen Messungen warten muss (vor allem bei dynamischen Werten wie wrap_content oder match_parent ), aber in der Regel ist diese Phase nicht auf onResume() . So brauchst du einen Workaround für das Warten auf diese Phase. Hier gibt es verschiedene mögliche Lösungen:

    1. Listen to Draw / Layout Events: ViewTreeObserver

    Ein ViewTreeObserver wird für verschiedene Zeichnungsereignisse ausgelöst. Normalerweise ist der OnGlobalLayoutListener das, was du willst, um die Messung zu erhalten, also wird der Code im Hörer nach der OnGlobalLayoutListener aufgerufen, also sind die Messungen bereit:

     view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); view.getHeight(); //height is ready } }); 

    Hinweis: Der Zuhörer wird sofort entfernt, da es sonst bei jedem Layout-Event ausgelöst wird. Wenn Sie apps SDK Lvl <16 verwenden müssen, verwenden Sie diese, um den Listener aufzuheben :

    public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)

    2. Hinzufügen einer Laufzeit zur Layout-Warteschlange: View.post ()

    Nicht sehr bekannt und meine Lieblingslösung. Grundsätzlich nur die Post-Post-Methode mit Ihrem eigenen Runnable verwenden. Dies grundsätzlich in der Warteschlange Ihren Code nach der Ansicht der Maßnahme, Layout, etc. wie von Romain Guy angegeben :

    Die UI-Ereigniswarteschlange verarbeitet Ereignisse in der Reihenfolge. Nachdem setContentView () aufgerufen wird, enthält die Ereignis-Warteschlange eine Meldung, die nach einem Relayout fragt, also wird alles, was du in der Warteschlange posten, nach dem Layout-Pass passieren

    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 nicht nach der Ausführung deaktivieren, was ein Streit sein kann
    • Weniger ausführliche Syntax

    Referenzen:

    3. Überschreiben Sie die OnLayout-Methode von Views

    Das ist nur in gewisser Situation praktisch, wenn die Logik in die Ansicht selbst eingekapselt werden kann, sonst ist dies eine ziemlich 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 } }; 

    Auch Verstand, dass onLayout wird viele Male genannt werden, also seien Sie rücksichtsvoll, was Sie in der Methode tun, oder deaktivieren Sie Ihren Code nach dem ersten Mal

    4. Überprüfen Sie, ob die Layoutphase durchgeführt wurde

    Wenn Sie Code haben, der mehrere Male während der Erstellung der ui ausgeführt wird, können Sie die folgende Unterstützung v4 lib-Methode verwenden:

     View viewYouNeedHeightFrom = ... ... if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) { viewYouNeedHeightFrom.getHeight(); } 

    Gibt true zurück, wenn die Ansicht mindestens ein Layout durchgeführt hat, seit es zuletzt an einem Fenster befestigt oder von diesem entfernt wurde.

    Zusätzlich: statisch definierte Messungen erhalten

    Wenn es genügt, nur die statisch definierte Höhe / Breite zu bekommen, können Sie dies einfach mit:

    • View.getMeasuredWidth()
    • View.getMeasuredHeigth()

    Aber denken Sie daran, dass dies anders sein kann als die tatsächliche Breite / Höhe nach dem Zeichnen. 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 Elternteil sein soll (siehe Layout für weitere Details). Die gemessenen Dimensionen können durch Aufruf von getMeasuredWidth () und getMeasuredHeight () erhalten werden.

    Das zweite Paar ist einfach als Breite und Höhe bekannt, oder manchmal Zeichnung Breite und Zeichnung Höhe. Diese Dimensionen definieren die tatsächliche Größe der Ansicht auf dem Bildschirm, beim Zeichnen und nach dem Layout. Diese Werte können sich aber nicht von der gemessenen Breite und Höhe unterscheiden. Die Breite und Höhe können durch Aufruf von getWidth () und getHeight () erhalten werden.

    Wir können benutzen

     @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); //Here you can get the size! } 

    Ich habe diese Lösung benutzt, was meiner Meinung nach besser ist als onWindowFocusChanged (). Wenn Sie ein DialogFragment öffnen, dann das Telefon drehen, wird onWindowFocusChanged nur dann 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: wie removeGlobalOnLayoutListener veraltet ist, solltest du jetzt 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) { container.getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { container.getViewTreeObserver().removeGlobalOnLayoutListener(this); } // Here you can get the size :) } 

    Wie Ian in diesem Android-Entwickler-Thread sagt:

    Jedenfalls ist der Deal, dass das Layout des Inhalts eines Fensters passiert, nachdem alle Elemente konstruiert und zu ihren übergeordneten Ansichten hinzugefügt wurden. Es muss so sein, denn bis du weißt, welche Komponenten eine Ansicht enthält und was sie enthalten, und so weiter gibt es keinen vernünftigen Weg, den du auslegen kannst.

    Bottom line, wenn Sie getWidth () etc. in einem Konstruktor aufrufen, wird es Null zurückgeben. Die Prozedur ist, alle Ihre View-Elemente im Konstruktor zu erstellen und dann auf die OnSizeChanged () -Methode des Views zu warten, um angerufen zu werden – das ist, wenn du zuerst deine echte Größe herausfindest, also, wenn du die Größen deiner GUI-Elemente einsetzest.

    Sei auch bewusst, dass onSizeChanged () manchmal mit Parametern von Null – Check für diesen Fall aufgerufen wird und sofort zurückkehren wird (also bekommst du bei der Berechnung deines Layouts keine Ungleichung bei Null.). Einige Zeit später wird es mit den realen Werten aufgerufen.

    Wenn Sie eine Breite von einem Widget erhalten 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(); 

    Ich würde lieber OnPreDrawListener() anstelle von addOnGlobalLayoutListener() , da es früher genannt wird.

      view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); // put your code here return false; } }); 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.