Device: Roku Ultra 4800RW, OS 16.0.4 build 834, 1080p (FHD channel)
Component: RowList, rowFocusAnimationStyle: “fixedFocus” or “fixedFocusWrap”
Severity: Medium. Item components that draw their own focus from focusPercent (e.g. scaling up as they take focus, with drawFocusFeedback off) are left partly focused after focus has moved on.
Summary
When focus moves one item to the RIGHT along a row, RowList animates focusPercent on both items: down from 1 on the item it leaves, and up from 0 on the item it moves to. The item it moves to reaches 1, but the item it leaves never reaches 0. RowList stops setting its focusPercent at around 0.06 to 0.09 and never sets it again. The field keeps that value, so this isn’t only a missed notification: reading focusPercent on the item component afterwards returns the same partial value. It stays there until focus comes back to that item, or a LEFT move passes over it.
Moving LEFT works correctly: the item focus leaves goes all the way to 0. floatingFocus is also correct in both directions. Only the styles where the row scrolls under a fixed focus are affected, and only when moving right.
Steps to reproduce
- Create a Scene containing a RowList with 3 rows of 12 items. Set rowFocusAnimationStyle: “fixedFocus”, vertFocusAnimationStyle: “fixedFocus”, drawFocusFeedback: false, itemSize: [1749, 330], rowItemSize: [[398, 330]], rowItemSpacing: [[24, 0]], rowHeights: [330], numRows: 3, and give it focus.
- Use an item component with a focusPercent field whose onChange prints the item’s id and the new value.
- Press DOWN to focus row 1, then press RIGHT once and wait for focus to come to rest.
- Read focusPercent on every item component (e.g. from a field each one observes) and print any that aren’t 0.
- Repeat with RIGHT taps at any speed, with LEFT taps, and with rowFocusAnimationStyle “fixedFocusWrap” and “floatingFocus”.
Expected
After each move, the item focus left has focusPercent 0 and the item focus moved to has 1, as with LEFT moves and with floatingFocus.
Actual
After every RIGHT move in fixedFocus or fixedFocusWrap, the item focus left has focusPercent between about 0.06 and 0.09, both as last notified and when read afterwards.
One RIGHT tap from [1,0] to [1,1] (fixedFocus, ms since launch). The two items are set as a pair adding up to 1 until the item being left stops at 0.090, while the other carries on alone to 1:
t=31437 fp r1i0 0.9383886 fp r1i1 0.06161137
t=31468 fp r1i0 0.5 fp r1i1 0.5
t=31593 fp r1i0 0.1232228 fp r1i1 0.8767772
t=31593 fp r1i0 0.09004742 fp r1i1 0.9099526 ← last value r1i0 is ever given
t=31625 fp r1i1 0.957346
t=31687 fp r1i1 0.9952607
t=31750 fp r1i1 1
t=31750 rowItemFocused [1,1]
(read afterwards: r1i0 focusPercent=0.09004742)
Results across runs (focusPercent left on each item focus moved off):
fixedFocus, 1 tap right: 0.076
fixedFocus, 3 taps right, 1.2s apart: 0.090, 0.090, 0.064 / 0.076, 0.073, 0.078
fixedFocus, 3 taps right, 0.3s apart: 0.081, 0.069, 0.064
fixedFocus, taps left (any speed): 0 every time
fixedFocusWrap, 2 taps right: 0.076, 0.083
fixedFocusWrap, 2 taps left: 0 every time
floatingFocus, either direction: 0 every time
Notes
- With an item component that scales up by focusPercent (with drawFocusFeedback off, the item draws its own focus), each item focus moves right from stays slightly enlarged. With focus growth and other logic in the item component, we’ve seen it left as high as 0.57 in our app, enough for an item that treats focusPercent >= 0.5 as focused to still think it has focus.
- Workaround: in the item component, once focusPercent has stopped changing part way for a moment (e.g. 0.2 s, several frames past RowList’s normal step interval), set it the rest of the way in the direction it was moving (0 or 1). Setting the item’s own focusPercent also makes RowList’s next set a change, so it’s still notified.
- A barebones channel that reproduces this is available. It logs every focusPercent change per item, and has an ECP input command (input?cmd=dump) that prints each item’s current focusPercent.
