Explain Codes LogoExplain Codes Logo

View's getWidth() and getHeight() returns 0

java
view-dimensions
custom-views
animations
Anton ShumikhinbyAnton Shumikhin·Aug 6, 2024
TLDR

The correct View dimensions are fetched post layout completion. If getWidth() and getHeight() run prematurely, they return 0 due to the unfinished layout. To get the dimensions after layout finalization use a ViewTreeObserver.OnGlobalLayoutListener:

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int width = view.getWidth(); int height = view.getHeight(); // Now, width and height aren't playing hide and seek anymore. // Avoid memory leaks and redundant calls: lose this number if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { view.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } });

Dimensions in lifecycle phases

If the lifecycle methods like onStart() or onResume() are called, it's a good time to get the view dimensions. In such events, layout process is expected to be complete. Specifically, during animations, use dimensions from onWindowFocusChanged for reliable size tracking.

Animations in the spotlight:

@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int width = view.getWidth(); int height = view.getHeight(); // Ready for some pirouettes? } }

Customizing view handling

Creating custom views? onLayout is the method to capture width & height. Although, keep in mind that onLayout is a diva: it appears multiple times on stage throughout the lifecycle.

@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { // This function is like your in-laws. Changes things every time it shows up. } }

For static view configurations

If the layout is static and unchanging, getMeasuredWidth() and getMeasuredHeight() should be your go-to tools. These offer the size the view intends to be, even when the layout hasn't come out of the dressing room yet.

Valid view sizing assurance

To ensure if your view has gone through its makeover and flaunts proper width and height values, check ViewCompat.isLaidOut(view).

if (ViewCompat.isLaidOut(view)) { // View's ready for the catwalk! int width = view.getWidth(); int height = view.getHeight(); }

To lineup a task on the view's message queue, which gets executed post layout, use View.post(Runnable):

view.post(() -> { int width = view.getWidth(); int height = view.getHeight(); // Get ready to strike a pose! });

Consistency across contexts

For maintaining consistent styling and sizing across various UI and to avoid hard-coded dimension values that may not account for varying screen sizes and densities, use dimension resources while inflating your custom UIs.

Effective animation use

Realize the difference between visible size during animations and actual interactive area of a view. For touch events, actual area is key. Make sure animated transformations don't ruin user's expectations by reducing touch target sizes unexpectedly.