J'ai une vue composée de TableLayout, TableRow and TextView
. Je veux qu'il ressemble à une grille. J'ai besoin d'obtenir la hauteur et la largeur de cette grille. Les méthodes getHeight()
et getWidth()
reviennent toujours 0. Cela se produit lorsque formater la grille dynamique et aussi lorsque j'utilise une version XML.
Comment récupérer les dimensions d'une vue?
Voici mon programme de test que j'ai utilisé dans Debug pour vérifier les résultats:
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()
etgetWidth()
après que le cycle de vie de l'activité ait demandé aux vues de se mesurer, en d'autres termes, de faire ce genre de chosesonResume()
et c'est tout. Vous ne devriez pas vous attendre à ce qu'un objet pas encore disposé connaisse ses dimensions, c'est tout le truc. Pas besoin de la magie suggérée ci-dessous.getHeight()/Width()
àonResume()
ne pas céder> 0 valeur pour moi.Réponses:
Je crois que l'OP est révolue depuis longtemps, mais au cas où cette réponse pourrait aider les futurs chercheurs, j'ai pensé publier une solution que j'ai trouvée. J'ai ajouté ce code dans ma
onCreate()
méthode:MODIFIÉ : 07/05/11 pour inclure le code des commentaires:
Je reçois d'abord une référence finale à mon
TextView
(pour accéder à laonGlobalLayout()
méthode). Ensuite, j'obtiens leViewTreeObserver
de monTextView
, et j'ajoute unOnGlobalLayoutListener
, redéfinissantonGLobalLayout
(il ne semble pas y avoir de méthode de superclasse à invoquer ici ...) et en ajoutant mon code qui nécessite de connaître les mesures de la vue dans cet écouteur. Tout fonctionne comme prévu pour moi, donc j'espère que cela pourra vous aider.la source
tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
cette façon, l'auditeur devrait être supprimé après la première fois ça arrive.addOnLayoutChangeListener
fonctionne aussi! :)Je vais simplement ajouter une solution alternative, remplacer la méthode onWindowFocusChanged de votre activité et vous pourrez obtenir les valeurs de getHeight (), getWidth () à partir de là.
la source
ViewTreeObserver
.Vous essayez d'obtenir la largeur et la hauteur d'un élément qui n'a pas encore été dessiné.
Si vous utilisez le débogage et arrêtez à un moment donné, vous verrez que l'écran de votre appareil est toujours vide, c'est parce que vos éléments n'étaient pas encore dessinés, donc vous ne pouvez pas obtenir la largeur et la hauteur de quelque chose, ce n'est pas encore exister.
Et, je peux me tromper, mais
setWidth()
n'est pas toujours respecté,Layout
expose ses enfants et décide comment les mesurer (appelchild.measure()
), donc si vous définissezsetWidth()
, vous n'êtes pas assuré d'obtenir cette largeur après que l'élément sera dessiné.Ce dont vous avez besoin, c'est d'utiliser
getMeasuredWidth()
(la mesure la plus récente de votre vue) quelque part après que la vue a été réellement dessinée.Regardez dans le
Activity
cycle de vie pour trouver le meilleur moment.http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Je crois qu'une bonne pratique consiste à utiliser
OnGlobalLayoutListener
comme ceci:Vous pouvez placer ce code directement dans
onCreate()
, et il sera invoqué lorsque les vues seront présentées.la source
Utilisez la méthode de publication de View comme celle-ci
la source
J'ai essayé d'utiliser
onGlobalLayout()
pour faire un formatage personnalisé d'unTextView
, mais comme @George Bailey l'a remarqué, ilonGlobalLayout()
est en effet appelé deux fois: une fois sur le chemin de mise en page initial, et une deuxième fois après avoir modifié le texte.View.onSizeChanged()
fonctionne mieux pour moi car si j'y modifie le texte, la méthode n'est appelée qu'une seule fois (lors de la mise en page). Cela nécessitait une sous-classification deTextView
, mais au niveau API 11+View. addOnLayoutChangeListener()
pouvez éviter cette sous-classification.Une dernière chose, afin d'obtenir une largeur correcte de la vue
View.onSizeChanged()
, lelayout_width
doit être défini surmatch_parent
, nonwrap_content
.la source
Essayez-vous d'obtenir des tailles dans un constructeur ou toute autre méthode exécutée AVANT d'obtenir l'image réelle?
Vous n'obtiendrez aucune dimension avant que tous les composants ne soient réellement mesurés (car votre xml ne connaît pas la taille de votre affichage, la position des parents, etc.)
Essayez d'obtenir des valeurs après onSizeChanged () (bien qu'il puisse être appelé avec zéro), ou attendez simplement quand vous obtiendrez une image réelle.
la source
Comme FX l'a mentionné, vous pouvez utiliser un
OnLayoutChangeListener
à la vue que vous souhaitez suivre lui-mêmeVous pouvez supprimer l'écouteur dans le rappel si vous souhaitez uniquement la disposition initiale.
la source
Je suppose que c'est ce que vous devez regarder: l'utilisation
onSizeChanged()
de votre point de vue. Voici un extrait de code ÉTENDU sur la façon d'utiliseronSizeChanged()
pour obtenir la hauteur et la largeur de votre mise en page ou vue dynamiquement http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.htmlla source
ViewTreeObserver
etonWindowFocusChanged()
ne sont pas si nécessaires du tout.Si vous gonflez la
TextView
disposition en tant que et / ou y mettez du contenu et que vous la définissez,LayoutParams
vous pouvez utilisergetMeasuredHeight()
etgetMeasuredWidth()
.MAIS vous devez être prudent avec
LinearLayouts
(peut-être aussi d'autresViewGroups
). Le problème est que vous pouvez obtenir la largeur et la hauteur après,onWindowFocusChanged()
mais si vous essayez d'y ajouter des vues, vous ne pouvez pas obtenir ces informations tant que tout n'a pas été dessiné. J'essayais d'en ajouter plusieursTextViews
pourLinearLayouts
imiter unFlowLayout
(style d'emballage) et je ne pouvais donc pas l'utiliserListeners
. Une fois le processus démarré, il doit se poursuivre de manière synchrone. Donc, dans ce cas, vous souhaiterez peut-être conserver la largeur dans une variable pour l'utiliser plus tard, car lors de l'ajout de vues à la mise en page, vous en aurez peut-être besoin.la source
Même si la solution proposée fonctionne, ce n'est peut-être pas la meilleure solution pour tous les cas car basée sur la documentation de
ViewTreeObserver.OnGlobalLayoutListener
ce qui signifie qu'il est appelé plusieurs fois et pas toujours la vue est mesurée (sa hauteur et sa largeur sont déterminées)
Une alternative consiste à utiliser
ViewTreeObserver.OnPreDrawListener
ce qui n'est appelé que lorsque la vue est prête à être dessinée et a toutes ses mesures.la source
Vous devriez plutôt regarder View lifecycle: http://developer.android.com/reference/android/view/View.html En général, vous ne devriez pas connaître la largeur et la hauteur avec certitude jusqu'à ce que votre activité atteigne l'état onResume.
la source
Vous pouvez utiliser une diffusion appelée dans OnResume ()
Par exemple:
Vous ne pouvez pas obtenir la hauteur d'une vue dans OnCreate (), onStart () ou même dans onResume () pour la raison que kcoppock a répondu
la source
La hauteur et la largeur sont nulles car la vue n'a pas été créée au moment où vous demandez sa hauteur et sa largeur. Une solution la plus simple est
Cette méthode est bonne par rapport à d'autres méthodes car elle est courte et nette.
la source
Réponse simple: Cela a fonctionné pour moi sans problème. Il semble que la clé consiste à s'assurer que la vue a le focus avant d'obtenir getHeight, etc. Faites-le en utilisant la méthode hasFocus (), puis en utilisant la méthode getHeight () dans cet ordre. Seulement 3 lignes de code requises.
ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1);
myImageButton1.hasFocus();
int myButtonHeight = myImageButton1.getHeight();
Log.d("Button Height: ", ""+myButtonHeight );//Not required
J'espère que ça aide.
la source
Utilisez getMeasuredWidth () et getMeasuredHeight () pour votre vue.
Guide du développeur: Afficher
la source
CORRECTION: J'ai découvert que la solution ci-dessus est terrible. Surtout lorsque votre téléphone est lent. Et ici, j'ai trouvé une autre solution: calculer la valeur px de l'élément, y compris les marges et les rembourrages: dp à px: https://stackoverflow.com/a/6327095/1982712
ou dimens.xml en px: https://stackoverflow.com/a/16276351/1982712
sp à px: https://stackoverflow.com/a/9219417/1982712 (inverser la solution)
ou dimens en px: https://stackoverflow.com/a/16276351/1982712
et c'est tout.
la source