Tedd, I'm quite sure that you don't want to do any of this in onDraw. It's just a thought, but suppose that measureHeight, in addition to remembering the width it had just returned, kept a number that represented the error in that width. When it returns, it requests a re-layout, unless that error is small. That would allow you to avoid the second thread altogether... a thread that is, surely, going to be hard to manage over your Activitiy's lifecycle.
-blake Programming Android, FTW! http://oreilly.com/catalog/0636920010364 On Sep 9, 1:48 pm, Ted Hopp <ted.h...@gmail.com> wrote: > I asked this question on > SO<http://stackoverflow.com/questions/7015097/best-practices-for-dealing...>a > month ago but got no answer. Maybe I'll have better luck here. :) > > I keep running into a sizing and layout problem for custom views and I'm > wondering if anyone can suggest a "best practices" approach. The problem is > as follows. Imagine a custom view where the height required for the content > depends on the width of the view (similar to a multi-line TextView). > (Obviously, this only applies if the height isn't fixed by the layout > parameters.) The catch is that for a given width, it's rather expensive to > compute the content height in these custom views. In particular, it's too > expensive to be computed on the UI thread, so at some point a worker thread > needs to be fired up to compute the layout and when it is finished, the UI > needs to be updated. > > The question is, how should this be designed? I've thought of several > strategies. They all assume that whenever the height is calculated, the > corresponding width is recorded. > > The first strategy is shown in this code: > > protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { > int width = measureWidth(widthMeasureSpec); > setMeasuredDimension(width, measureHeight(heightMeasureSpec, width)); > > } > > private int measureWidth(int widthMeasureSpec) { > // irrelevant to this problem > > } > > private int measureHeight(int heightMeasureSpec, int width) { > int result; > int specMode = MeasureSpec.getMode(measureSpec); > int specSize = MeasureSpec.getSize(measureSpec); > if (specMode == MeasureSpec.EXACTLY) { > result = specSize; > } else { > if (width != mLastWidth) { > interruptAnyExistingLayoutThread(); > mLastWidth = width; > mLayoutHeight = DEFAULT_HEIGHT; > startNewLayoutThread(); > } > result = mLayoutHeight; > if (specMode == MeasureSpec.AT_MOST && result > specSize) { > result = specSize; > } > } > return result; > > } > > When the layout thread finishes, it posts a Runnable to the UI thread to set > mLayoutHeight to the calculated height and then call requestLayout() (and > invalidate()). > > A second strategy is to have onMeasure always use the then-current value for > mLayoutHeight (without firing up a layout thread). Testing for changes in > width and firing up a layout thread would be done by overriding > onSizeChanged. > > A third strategy is to be lazy and wait to fire up the layout thread (if > necessary) in onDraw. > > I would like to minimize the number of times a layout thread is launched > and/or killed, while also calculating the required height as soon as > possible. It would probably be good to minimize the number of calls to > requestLayout() as well. > > From the docs, it's clear that onMeasure might be called several times > during the course of a single layout. It's less clear (but seems likely) > that onSizeChanged might also be called several times. So I'm thinking that > putting the logic in onDraw might be the better strategy. But that seems > contrary to the spirit of custom view sizing, so I have an admittedly > irrational bias against it. > > Other people must have faced this same problem. Are there approaches I've > missed? Is there a best approach? -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en