I am evaluating Fuse for developing TV interfaces on Android. The first thing I am trying to do is to generate a couple of menu ‘buttons’ on-screen, and to accept key input (up/down) to move focus between them.
The ‘buttons’ are fully graphical - with an image for focus and no-focus states. My first attempt was to draw two buttons to screen, and for each button to change image when given focus.
The buttons get rendered correctly, but clicking on a button does not display the focus image.
Any thoughts on how this may best be accompished? I’m happy enough to take control over managing the focus state, but wasn’t sure how to set an image based on some external state.
Any thoughts or directions welcomed.
<App Theme="Basic" Background="#eeeeeeff">
<Panel>
<FileImageSource ux:Key="btn_1" File="Assets/btn_1.png" />
<FileImageSource ux:Key="btn_1_f" File="Assets/btn_1_f.png" />
<FileImageSource ux:Key="btn_2" File="Assets/btn_2.png" />
<FileImageSource ux:Key="btn_2_f" File="Assets/btn_2_f.png" />
<JavaScript>
var Observable = require("FuseJS/Observable");
var menu = [
{
name : 'button_1',
background : 'btn_1',
background_focus : 'btn_1_f',
position : {
x:100,
y:100,
w:200,
h:50
},
next_up : null,
next_down : "button_2"
},
{
name : 'button_2',
background : 'btn_2',
background_focus : 'btn_2_f',
position : {
x : 100,
y : 155,
w : 200,
h : 50
},
next_up : "button_1",
next_down : null
},
];
var currentFocus = Observable(menu[0].name); //Give focus to the first button
module.exports = {
currentFocus : currentFocus,
menu : menu
}
</JavaScript>
<Each Items="{menu}">
<Panel X="{position.x}" Y="{position.y}" Width="{position.w}" Height="{position.h}" Focus.IsFocusable="true" >
<Image Source="{DataToResource background}" />
<Tapped>
<GiveFocus/>
</Tapped>
<WhileFocused>
<Image Source="{DataToResource background_focus}" />
</WhileFocused>
</Panel>
</Each>
</Panel>
</App>
Many thanks - that seems to do the trick! For reference, I’ve updated your solution to read the next focus elements in each direction from the menu item config object itself. Also, I’ve enabled focussing of an element by tapping gesture as well.
Obviously, handlers for left and right could be added to make this more universal.
<App Theme="Basic" Background="#eeeeeeff">
<Panel>
<FileImageSource ux:Key="btn_1" File="Assets/btn_1.png" />
<FileImageSource ux:Key="btn_1_f" File="Assets/btn_1_f.png" />
<FileImageSource ux:Key="btn_2" File="Assets/btn_2.png" />
<FileImageSource ux:Key="btn_2_f" File="Assets/btn_2_f.png" />
<JavaScript>
var Observable = require("FuseJS/Observable");
var focus_element;
var menu = [
{
id : 'button_1',
background : 'btn_1',
background_focus : 'btn_1_f',
focus_vis: Observable('Hidden'),
position : {
x:100,
y:100,
w:200,
h:50
},
next_up : null,
next_down : "button_2"
},
{
id : 'button_2',
background : 'btn_2',
background_focus : 'btn_2_f',
focus_vis: Observable('Hidden'),
position : {
x : 100,
y : 155,
w : 200,
h : 50
},
next_up : "button_1",
next_down : null
}
];
//Give the first button focus
setfocus(menu[0].id);
function setfocus(element_id) {
var target_element = findElement(element_id);
if (!target_element){
//Could not find element
console.log("Error : Could not find element '" + element_id + "'");
}
else{
//Turn off the previous button
if (focus_element){
focus_element.focus_vis.value = "Hidden";
}
//Highlight the new button
focus_element = target_element;
focus_element.focus_vis.value = "Visible";
}
}
function findElement(element_id){
var matched_elements = menu.filter( function(obj){
return obj.id == element_id
});
if (!matched_elements || matched_elements.length == 0){
return(null);
}
else
{
return(matched_elements[0]);
}
}
function up (e) {
if (focus_element.next_up){
setfocus(focus_element.next_up);
}
}
function down () {
if (focus_element.next_down){
setfocus(focus_element.next_down);
}
}
function elementTapped(e){
if (e.data.id){
setfocus(e.data.id);
}
}
module.exports = {
menu : menu,
up: up,
down: down,
elementTapped : elementTapped
}
</JavaScript>
<KeyTrigger Key="Up"><Callback Handler="{up}" /></KeyTrigger>
<KeyTrigger Key="Down"><Callback Handler="{down}" /></KeyTrigger>
<Each Items="{menu}">
<Panel X="{position.x}" Y="{position.y}" Width="{position.w}" Height="{position.h}" Focus.IsFocusable="true" >
<Tapped>
<Callback Handler="{elementTapped}"/>
</Tapped>
<Image Source="{DataToResource background_focus}" Visibility="{focus_vis}" />
<Image Source="{DataToResource background}" Visibility="Visible" />
</Panel>
</Each>
</Panel>
</App>