Though it's worth noting that the SpeechBubble module behaves a little differently from AGS Character.Say() in this respect:
With Character.Say(), as near as I can tell, the text positioning is always based on the height of the (first frame in the) NormalView â€" unless it has been Locked to some other view â€" even if speech starts while an Idle view is playing. Character.SayBubble(), on the other hand, uses the current view at the time when speech starts, so if the idle animation is playing at that moment, it goes by the height of the Idle view. (I believe it can also be the SpeechView, if the character it already speaking.)
I can't see any way to determine whether the current view (if different from the NormalView) has been set with LockView() or is playing for some other reason, so I'm not sure it's possible to completely match the AGS behavior here.
With Character.Say(), as near as I can tell, the text positioning is always based on the height of the (first frame in the) NormalView â€" unless it has been Locked to some other view â€" even if speech starts while an Idle view is playing. Character.SayBubble(), on the other hand, uses the current view at the time when speech starts, so if the idle animation is playing at that moment, it goes by the height of the Idle view. (I believe it can also be the SpeechView, if the character it already speaking.)
I can't see any way to determine whether the current view (if different from the NormalView) has been set with LockView() or is playing for some other reason, so I'm not sure it's possible to completely match the AGS behavior here.