Après avoir mesuré une View
avec une dimensions constantes avec view.measure()
, les fonctions getMeasuredHeight()
et getMeasureWidth()
renvoient 0.
layout_view.xml , disposition gonflée pour créer la vue
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="100dp"
Android:layout_height="100dp">
</FrameLayout>
fonction qui mesure les dimensions
public void measureView(Context context){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.layout_view,null,false);
view.measure( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Log.d(TAG,"Error width : " + view.getMeasuredWidth());
Log.d(TAG,"Error heeght : " + view.getMeasuredHeight());
}
Lorsque vous appelez view.getMeasuredWidth()
dans onCreate()
ou onCreateView()
, la view
n'a pas encore été dessinée. Vous devez donc ajouter un auditeur et obtenir un rappel lorsque la variable view
est en cours d’extraction. Juste comme ça dans mon code:
final ViewTreeObserver vto = view.getViewTreeObserver();
if (vto.isAlive()) {
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int viewWidth = view.getMeasuredWidth();
// handle viewWidth here...
if (Build.VERSION.SDK_INT < 16) {
vto.removeGlobalOnLayoutListener(this);
} else {
vto.removeOnGlobalLayoutListener(this);
}
}
});
}
NOTE: Supprimez l'auditeur pour de meilleures performances!
N'appelez pas vto.removeOnGlobalLayoutListener(this)
pour supprimer l'auditeur. Appelez ça comme ça:
vto.getViewTreeObserver()
Mesurez-vous la vue dans onCreate()
. La vue n'est pas encore dessinée. Vous devez attendre un certain temps après le dessin de la vue avant de pouvoir la mesurer.
La solution simple pour cela consiste à poster un exécutable à la mise en page. Le runnable sera exécuté après la mise en page.
Pour plus d'informations Voir cet article
Edit Essayez de changer
view.measure( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
à
view.measure( View.MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY);
Essayez de cette façon, espérons que cela vous aidera à résoudre votre problème.
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
si la visibilité de votre vue mesurée est définie sur parti, la mesure retournera 0. Vous pouvez la définir sur visible, mesurer, puis redéfinie sur «disparu», le tout à partir du code.
Juste au cas où quelqu'un rencontrerait ce problème avec ImageView:
J'ai remarqué que si votre ImageView n'a pas "Android: src" défini (c'est-à-dire que vous le changez dynamiquement), il retournera toujours zéro à partir de getMeasuredWidth/Height.
Une solution de contournement simple consisterait à définir un espace réservé pour la vue.
Vous ne pouvez pas utiliser View.MeasureSpec.*
directement dans l'appel measure
. Au lieu de cela, utilisez d'abord makeMeasureSpec()
, puis utilisez-le pour appeler measure()
:
final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT/*can be match_parent or some exact value*/, View.MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT/*can be match_parent or some exact value*/, View.MeasureSpec.UNSPECIFIED);
view.measure(widthMeasureSpec, heightMeasureSpec);