Get dimensions of RelativeLayout at run-time

1.4k views Asked by At

I am trying to get the dimensions of the width and height in pixels of the RelativeLayout that I highlighted in red in the below picture.

enter image description here

In my code below, for testing purposes, I am setting the text of the Button in the RelativeLayout to the width of the whole layout (circled in blue in the picture). In the picture you can see the width is returning the value of 0. Below is my code.

@Override
protected void onCreate(Bundle savedInstanceState) {        
    super.onCreate(savedInstanceState);

    relativelayout = new RelativeLayout(getApplicationContext());
    puzzleRL = new RelativeLayout(getApplicationContext());

    puzzleLayout();

    puzzleRL.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            puzzleRL.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            puzzleWidth = puzzleRL.getWidth();
            puzzleHeight = puzzleRL.getHeight();
        }
    });

    levelCounter.setText("" + puzzleWidth);

    setContentView(relativelayout);
}

public void puzzleLayout() {

    // define puzzle space boundaries
    RelativeLayout.LayoutParams params0 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    params0.addRule(RelativeLayout.BELOW, view0.getId());
    params0.addRule(RelativeLayout.ABOVE, view3.getId());
    relativelayout.addView(puzzleRL, params0);

}

I've looked around and it seems like I need to utilize the onWindowFocusChanged(boolean hasFocus) method, which I have. But it still returns 0 as the width. I even tried putting all of my declarations from my onCreate() method and all of the layout code that is currently in the puzzleLayout() method into the onWindowFocusChanged(boolean hasFocus) method and but it still didn't return the correct thing.

Is onWindowFocusChanged(boolean hasFocus) the incorrect way to do this? Or am I possibly getting the dimensions getWidth()/getHeight() incorrectly?

EDIT I have altered my code to reflect suggestions from commenters. However, the levelCounter TextView is still outputting 0. Any ideas?

2

There are 2 answers

8
ramaral On BEST ANSWER

The width and height of a Layout, when they are not explicitly defined, are given only after all children are drawn.

This is the code i use:

//layout = (RelativeLayout) findViewById(R.id.layout);

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

    @Override
    public void onGlobalLayout() {

    // Ensure you call it only once :
        layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        width = layout.getWidth();// width must be declare as a field
        height = layout.getHeight;// height must be declare as a field
        levelCounter.setText("" + width);ยด
    }
});  

It must be in onCreate.

0
Junior Buckeridge On

You may want to move your code to onResume(), rather than keeping it in onWindowsFocusChanged(), because the latter is called whenever the activity changes focus (gains or loses focus). Don't forget to execute your code just once using a flag (or similar). Otherwise you will recreate all the buttons everytime.

By the way, you may want to try:

bList[0].setText(String.valueOf(w));

Edit: All the cretion code should be in onCreate(). Inside onResume() which is part of the visible phase of an activity, you can gt the dimension:

puzzleRL.measure(0, 0);
puzzleRL.getMeasuredHeight();
puzzleRL.getMeasuredWidth();

You can also post a delayed Runnable (500ms delay) to a Handler to do the measurement after onResume. Hope it works for you.