Measure Recyclerview before it appears
Asked Answered
F

3

10

I am currently experiencing an issue when measuring a recyclerView before it appears. I need the measuredHeight in order to start an "expand" animation.

This was previously done for a gridView in the code I'm working on and I am trying to migrate it to a RecyclerView with GridLayoutManager

final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, View.MeasureSpec.AT_MOST);
mGridView.measure(widthSpec, heightSpec);
int targetHeight = mGridView.getMeasuredHeight();

It was working with the gridView but if I call measure method with same measure specs on the recyclerView, result is always 16777215 which I think might be a max value for something but I cannot say what.

I saw some post explaining that a view can be measured before it is rendered on screen by measuring it with following measure specs :

final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);

but I get 0 for recyclerView.getMeasuredHeight();.

Is there a way to properly measure the height of the recyclerView before it is rendered on screen ?

Thanks.

Fanning answered 22/10, 2014 at 22:5 Comment(0)
K
1

Are you trying to measure the view before adding it? If so, that is dangerous.

Also, in terms of RecyclerView, unfortunately, existing layout managers don't yet support WRAP_CONTENT. They rely on the base implementation which supports match_paren & exact dimensions.

If you know your item's height, you can extend GridLayoutManager, override onMeasure and measure it there yourself.

Kohinoor answered 22/10, 2014 at 23:39 Comment(3)
Thanks for your answer. WRAP_CONTENT being unsupported could explain the issue. Someone apparently reported it : code.google.com/p/android/issues/detail?id=74772& . The view is inflated from xml layout file so it is added to view hierarchy. Unfortunately I do not know children's height as I have several adapters that can be passed to the recyclerView and they can display different items. I guess if I can retrieve the layout used for an item, I could inflate it, measure it and then calculate the gridLayoutManager height. I will try it out.Volva
I saw you've already fixed the issue. If you need a generic solution, you can also let the first measure pass occupy all space then request another layout and in the next measure pass, you can return the coordinate of the last child (getDecoratedEnd(view)). You can do this by simply checking # of views in onMeasure call might be sufficient if adapter size is always greater than 0. Hopefully, we'll get this in the upcoming releases.Kohinoor
Unfortunately, when I first call my expand method where I need to measure the view, I just created and filled in the adapter. When I want to any child view, the recyclerview does not contain any children. I guess it has to draw itself at least once to have references to children views ?Volva
F
2

Thanks to yigit post, I could finally calculate future recyclerView height by manually inflating a child's view, measuring it with :

final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, View.MeasureSpec.AT_MOST);

And finally multiplying its measuredHeight by the number of lines contained in the gridLayoutManager. Hope WRAP_CONTENT support will come soon for RecycleViews layoutManagers.

Fanning answered 23/10, 2014 at 11:13 Comment(0)
K
1

Are you trying to measure the view before adding it? If so, that is dangerous.

Also, in terms of RecyclerView, unfortunately, existing layout managers don't yet support WRAP_CONTENT. They rely on the base implementation which supports match_paren & exact dimensions.

If you know your item's height, you can extend GridLayoutManager, override onMeasure and measure it there yourself.

Kohinoor answered 22/10, 2014 at 23:39 Comment(3)
Thanks for your answer. WRAP_CONTENT being unsupported could explain the issue. Someone apparently reported it : code.google.com/p/android/issues/detail?id=74772& . The view is inflated from xml layout file so it is added to view hierarchy. Unfortunately I do not know children's height as I have several adapters that can be passed to the recyclerView and they can display different items. I guess if I can retrieve the layout used for an item, I could inflate it, measure it and then calculate the gridLayoutManager height. I will try it out.Volva
I saw you've already fixed the issue. If you need a generic solution, you can also let the first measure pass occupy all space then request another layout and in the next measure pass, you can return the coordinate of the last child (getDecoratedEnd(view)). You can do this by simply checking # of views in onMeasure call might be sufficient if adapter size is always greater than 0. Hopefully, we'll get this in the upcoming releases.Kohinoor
Unfortunately, when I first call my expand method where I need to measure the view, I just created and filled in the adapter. When I want to any child view, the recyclerview does not contain any children. I guess it has to draw itself at least once to have references to children views ?Volva
T
0

See also How do I make WRAP_CONTENT work on a RecyclerView.

If you place your RecyclerView inside a container such as RelativeLayout or NestedScrollView, you can obtain it's measures with recyclerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) or other variants you like. Before measuring it would be better to call post { /* measure here */ }.

Tweezers answered 27/11, 2019 at 16:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.