I have built UI that works perfectly with mouse input but I’m trying to make it work with the gamepad. It looks like keyboard/gamepad navigation works out of the box for most people, especially all the tutorial videos I’ve wathced. However now that I’m actually skinning my UI to look fancier instead of default unreal UI, things get a bit complicated. The documentation on the subject of keyboard focus seems to be lacking a bit since it tends to just work for people normally.
As I go left and right I want different columns of lists to take focus and become scrollable. Up/Down would select items in the list and scroll up/down as needed.
Keyboard navigation seems to start having trouble since I have all these fancy tricks where I have widgets wrapping other widgets to trick unreal into positioning everything just right and allow me to do outer glow effects on things as they highlight without clipping.
Here my list widget actually goes way out of bounds but the cells themselves have content that’s wrapped multiple times to offset the contents.
Each cell actually contains a hidden button which I would want focus to land on.
What seems to be happening is as I navigate, unreal automagically focuses the cells themselves and not the contents of the cells, even though the outer wrapper views shouldn’t be focusable. If I try to focus the views manually by propagating focus to children in the onFocusReceived event, I get yellow warnings from unreal saying the views have isFocusable set to false. Also as I push enter the buttons don’t trigger. But if I tap a button manually with a mouse and reenter keyboard focus mode the button is focused and pushing enter triggers the buttons.
I’m not quite sure how to force unreal to land focus on a specific child within a view instead of whatever outermost child it chooses.
Also the lists don’t seem to scroll as I select different items which I was hoping would happen automatically for me. It almost seems like maybe I have to not allow the lists to be focusable at all and do this manually somehow.
I have seen that but list and grid views are bit complex in that the cells are dynamically allocated and recycled as you scroll.
If I have a list of 50 items there may only exist 5 instances of cells, and I expect the list view to handle scrolling for me as I change focus on elements. As you scroll down, cell 0 may actually now be reused for element 6, then element 7 reuses cell 1, etc…
This is all handled deep within Slate C++ code and cells receive a OnListItemObjectSet callback to populate themselves with data. I’m not actually using a vertical box and manually setting its contents, even though that would normally make things much easier, but not scale at all for huge lists of objects.
Normally focusing and scrolling should be handled by the list view but due to all the nested widgets and buttons I have going on, it seems to not work out of the box. I am starting to think that I may have to programmatically set those navigation rules you showed as cells populate themselves with elements in the OnListItemObjectSet event.
The List view spits out the underlaying Item data and the pertinent widget onEntryInitialised. Perhaps you could track which widgets are initialised / active? But not sure how you’d handle escaping a widget, since the next widget has yet to exist.
The things with the list view is that it does not really keep the exact number of needed widgets. It actually holds double of that, roughly. The ones that have recently disappeared are still valid.
I might be underestimating the complexity of the scenario, of course.
The index of each widget changes on the fly too and I already handle knowing which index in the list each element is. (This is how I am able to do that alternating grid pattern in the backpack) Also widgets that have been allocated may become unused if elements from the list disappear and it doesn’t fill the whole view.
So maybe I can tell each widget to focus on the next widget manually depending on its index as it populates. Scrolling is going to be annoying too. I may have to handle that manually. If I’m at item index 5 and item index 6 is out of view, then I have to somehow trigger the list to scroll down to see list item 6 and then navigate.
I actually just realized that a lot of things don’t work because my lists have selection mode set to None because I handle widget selection myself with hidden buttons in each cell.
I tried creating a very basic list widget and everything works perfectly only if the list is set to at least single selection mode. Page up/page down/home/end keys all work.
But with no selection mode, the only thing focusable is the list widget itself and it’s impossible to focus on the cells or use page up, etc, keys to scroll.
I’m going to do some experiments with making the buttons in each cell themselves not focusable but allowing the list to be selectable so keyboard focus can actually work on its items.
There appears to be a bug with unreal not rendering the focus ants outline on my child button so I assumed focus was disappearing, but it’s all actually working otherwise. I’m now able to hit enter and it “Clicks” the button, and use my arrow keys to scroll up and down on different list elements. I just need to make my cells update their highlight state properly as the button gains keyboard focus.
I plan on disabling the focus ants outline anyway once this is all done so, works for me…
EDIT: Wait that wasn’t a bug. The default setting wasn’t “Always” for rendering the focus ants outline. That actually set me back by a few days since things were working that I thought weren’t working. Since focus was set programmatically the outline disappeared due to the “Navigation Only” setting.