EVALUATION
The index passed into getViewIndexAtPosition() should by nature be always inside bounds of the FlowView, so it was supposed that there will always be a child view at that index. This is why our code does not protect against -1. Here's why this supposition fails:
When a GlyphView is a fragment, i.e. it represents a piece of an element, it keeps an offset and length of that piece. Now if our view is in the end of an element, and we append a character to the end of that element, the view will be out of sync. The element's end offset will grow by 1 but the view's end offset will remain the same. Thus we have a 'gap' between glyph views: a character not covered by any view. If our view is the last view in its parent, there will be a gap between parent views as well.
This is why the code in question fails: a GlyphView fragment 'lags' behind its element. If it happens to be at the end of a row, we have a gap between rows. The index we pass into getViewIndexAtPosition() falls into that gap, so no View is found.
The purpose of this code is to find a row that we can safely start layout from (i.e. no rows before that row will be changed). Various recovery strategies are possible here. We could restart layout from row 0, or call getViewIndexAtPosition() again passing index decremented by one. I prefer the former option, as it keeps things simple.
|