3

My original problem was needing to know the height and width of my root View so that I could make programmatic layout changes. For my purposes, I don't necessarily need to determine this information during onCreate(); it's quite sufficient for me to programmatically add my child Views after layout of the root has completed, so therefore I'm happy to use onWindowFocusChanged() as a hook to determine when calling the root View's getWidth() and getHeight() will return valid results.

However, I see quite a few people have asked how to determine the root View's size during onCreate(). I'm guessing people want to do this for better user experience - perhaps so that users don't see the layout being built in stages (if anyone can clarify the reasons, I'd appreciate it). Now, the answer I have commonly seen given to this, such as the one here, is to post a Runnable to the root View within onCreate(). Inside that Runnable we perform the getWidth(), etc. The reason why this works is because, apparently, Runnable objects posted to a View are executed when the View has layout and / or is attached to the window.

This brings me to my question. In the API documentation for View, it doesn't seem to describe this behavior. So, can anyone tell me where it is defined and documented? Or, is it a matter of inspecting the source? Is it an absolutely and rigidly defined feature that Runnables will stay in a View's queue and only be handled at a certain point after the layout process?

Further clarification: On reading Kerry's answer and thinking it over a bit more, my basic question can be clarified as follows: In the answer given here and also in this CodeProject entry, I understand that we get around the problem of the root View's dimensions not being available during the onCreate() by posting a Runnable to the View. As Kerry points out, the guarantee is that this message Runnable cannot be executed until onCreate() has executed. I understand that layout occurs some point after onCreate, but I still can't grasp at the moment why this Runnable should execute when the View's dimensions are known.

Community
  • 1
  • 1
Trevor
  • 10,903
  • 5
  • 61
  • 84
  • Just further to your additional info. The examples you gave in CodeProject in my opinion not so good. I think the post() method should be called in the onSizeChanged() method of the child view. They way they have done it I'm not 100% convinced even the Root views size will be known (if calling from child.onCreate()). Calling from child.onSizeChanged() the root view MUST have size for it to allow the child to be drawn. Consequently that's why I say call it from the onSizeChanged() method. – D-Dᴙum Jul 05 '12 at 11:40
  • 1
    I agree, and for my purposes I will take your advice and use `onSizeChanged()`. But, the fact that it is Romain Guy who recommended the post() method (http://stackoverflow.com/questions/3602026/linearlayout-height-in-oncreate-is-0) makes me believe that there is something well defined in the APIs that guarantees that the `View` will process the `Runnable` only when it has layout. I guess this is all academic really, but I would like a further understanding as to why that is. I posted a comment to Romain. – Trevor Jul 05 '12 at 11:50

1 Answers1

1

I had a look at the View.post(Runnable) method and it seems to me that by calling that method you are just adding a message to the UI thread queue. The only thing that is going to be 'guaranteed' is that the Runnable will be executed sometime AFTER the method which has called post(Runnable) has completed. This assumes you are calling post(Runnable) from the UI thread but as the docs say:

This method can be invoked from outside of the UI thread only when this View is attached to a window.

I think to be sure that both your Root view and Child view both have size, you would need to call post(Runnable) from the child onSizeChanged() method because if the child has size I think it follows that the Parent i.e. Root view therefore must have size too.

Apologies if this is a bit of a rambling answer. I kind of understand what you're wanting to achieve but not 100% sure. Let me know if you want me to clarify anything.

Personally whenever I've needed the size of a View I do everything in onSizeChanged() which I do believe is the 'correct' way of doing it and it has always worked.

D-Dᴙum
  • 7,689
  • 8
  • 58
  • 97
  • Thank you. I think I should be the one apologising for doing the rambling. Though my question talks about obtaining root height / width, specifically what interests me is how I've seen it recommended in several places (e.g. http://www.codeproject.com/Tips/313848/Get-actual-screen-size-for-the-application-layout) that posting a `Runnable` to a `View` is a way to execute code when that `View` is attached to window. What confuses me is that I can't see it defined in any documentation anywhere about what point during / after a layout process a `View` starts to process the queue messages. – Trevor Jul 05 '12 at 10:48
  • I'm assuming (and I think quite safely) that processing of messages is just an inherent function of a View. In fact I think it's part of Java. Consequently it's not explicitly described/detailed in the API docs but it's kind of inferred. Actually it's just dawned on me that is it your concern that a View could 'process' a message (sent by a call to Post(Runnable) made by your code) before the View has size? If so I would say it might be possible depending on how it's done. But if you're calling it from the onSizeChanged() method as I mentioned you're guaranteed the View has size. – D-Dᴙum Jul 05 '12 at 11:02