Good question, the answer is a bit mysterious though. In this case, since we call doOnLayout{}
and doOnNextLayout{}
before the view is laid out, in both cases, it adds an OnLayoutChangeListener
. This listener is called while the view is still being laid out, but after onLayout()
. So, any code inside doOnLayout{..}
is done during the layout phase which makes things a bit complicated.
The first doOnLayout{}
gets the collapsed height, then does expandView.isVisible = true
which triggers another layout pass. onDraw()
never gets called because visiblity was changed during the layout phase. In the next layout phase, doOnNextLayout{}
, we get the expanded height but we need to collapse it again to make it seamless to the user.
The problem here is, doing expandView.isVisible = false
here doesn’t trigger a new layout pass. I tested this a bit, turns out, when you set visbility GONE
to a view during layout, it doesn’t trigger a new layout. Which is why we use post{}
to hide the view again which is called after layout.
While writing this answer, I tried using View.doOnPreDraw{..}
instead. This works much better in this scenario because it’s called after layout is done (before onDraw). So, we don’t have to use the post{}
trick anymore.