I have a FrameLayout with a 100 views (TextViews).
At some point I need to modify the width of 10 views.
Calling requestLayout() on 10 children as you know triggers a layout pass of all 100 views and it is very slow.
Is there a way to change only the width of these 10 views ?
I don't know if I explained well the problem. Basically what I need is to remeasure the View (TextView) so it will redraw itself using the new width value.
Related
I have implemented some custom views in Android and one of the most frequent problems I have is to adapt the layout to the screen, weather by matching the parent's content, MATCH_PARENT, or wrapping its own content, WRAP_CONTENT. The ConstraintLayout, for instance, does not support WRAP_CONTENT.
The trouble starts when I have to adapt the children size, which initially I was doing on onLayout. One use case of this is when I want to have children which width and height respect a certain aspect ratio; and the width grow as much as possible.
So, in my onLayout, if changed was true I had reset constraints reset. However, it was causing a loop, since it changes the layout again.
What would be the proper place to size the custom widget children?
onSizeChanged or onMeasure?
I want to create a custom diagonal layout like androids predefined linear layout..so i started with a class extending ViewGroup and overrided OnLayout and OnMeasure methods..However I am finding it difficult to understand where to write the logic for alligning all the Views such that they will be placed diagonally
I read few blogs on it How to Create Custom Layout in Android by Extending ViewGroup Class
Also followed the google I/O video
But still not clear about how to get started with creating a diagonal layout..can someone suggest any additional resources in this regard..???
The logic to measure children should be in onMeasure. In here, you want the sum of all children height to be as big as the height given in the heightMeasureSpec. Same goes for the width.
To do so, you can divide the width and height from measureSpec by the number of children, and call the child views measure method with those computed values.
The logic to position the children is in onLayout. In here, you call the child views layout method one after another, passing it positions (left, top, ...) incremented after layouting each child.
You must take care of child views margins in both methods, as well as your container padding.
Lucas Rocha has a very good article (with lot of reverse engineering) for custom views.
I Have some really strange problems.
First problem is as follow:
I read how to override onMeasure(). I did it. I was expecting that when I set width/height in onMeasure that they will be exactly the same in onDraw, but apparently this is not true.
Also I except that measuredWidth will be same as width in draw phase, but again it isn't true.
onMeasure could be called many times. On each call I invoke setMeasuredDimension with calculated width and height. So for example, first time my view should be 480 x 245, on second call I recalculate it again, based on parent of course, and it should be 90 x 245.
For my great surprise android somehow is just ignoring everything but the first call. So in this case my final view size is 480 x 245.
Second issue which is as follow:
My view height is match_parent, my parent height is 0. So how am I supposed to set right height on onMeasure when I don't know it ?
Any Idea how to make android not to ignore my setMeasureDimensions calls and how to set match_parent ?
The space that's allocated to your view doesn't depend only on the size you measured, here's a snapshot of the process :
View.onMeasure gets called during the measurement of your parent. You got your MeasureSpec that is essentially how much space at most you can take (very summarized).
Given these specs, you determine the size of yourself, logically measuring your own children and calling setMeasuredDimension
A while after, your parent assigns you concrete dimensions, based on what you measured (but this also means it can be different). Then as these will be your dimensions, that's the one you have to use. The callback called at this point is onLayout, and you shall layout your children in the process, based on the dimensions that were affected to you.
After all this, your View will be drawn, that is View.dispatchDraw being called and resulting for simple views to onDraw. Drawing yourself also means drawing your children if you're a ViewGroup.
When drawing, the system passes a Canvas whose dimensions are these of the screen, and using translation and clipping, the canvas is passed along views so that they draw themselves. This avoids allocation during draw. For this reason, if your want to know what space is dedicated to you, you should not use Canvas.getWidth or Canvas.getHeight which are the dimensions of the screen, but rather retrieve the clipped dimensions (Canvas.getClipBounds())
And finally, when you correctly retrieve the clip bounds, they should usually be the same as your width and height (View.getWidth or View.getHeight), but they might be different, for example if the canvas was scaled.
So to summarize :
onMeasure purpose, is to determine the size of children, so that ViewGroup can compute they're dezired size.
onLayout purpose is to affect a width and height to each view, propagating to children.
onDraw purpose is to render your view.
I have an imageView with layout_width="match_parent".
On my adapter's getView(), I'd like to get the actual width of this imageView but don't know how.
I tried using imageView.getWidth(), but this returns 0.
The view is not attached to its parent group in getView(), so it hasn't been measured, hence the zero width. The only way I can think of is to do a parent.getWidth() which returns the width of the ViewGroup. This will only work when your view is not going to be placed next to another view in parent. This is usually the case for ListView, so may work for your case.
i have a scroll view, that has a relative layout in it. the content of this scrollview varies, and you may not get the full content at first time.
example, at time 0, onCreate completely executed, current height is 500dip, but at time 5, because some items in the content is fetching results asynchronously, once completed, it will display the result, so at time 5, the height of the content in scroll view can become 600dip
my goal is to have an overlay on top of the content in the scroll view, which should cover the view entirely i.e. height should be the same.
because the height can grow at any size, at different time, i don't think i can set height of the overlay to match_parent
how can i do this in android?
is there a method where i can get notified when the scroll view or relativelayout 's height is growing?? so that whenever it is updated to a larger height, i can change my overlay's height dynamically as well..?
any other method i can consider too
thanks!!
ScrollView inherits from FrameLayout and FrameLayout has an onSizeChanged() method. I would extend ScrollView and override that method so you can capture size changes. This might work for you.