Changing UI Properties on Runtime
There will always be a need to change properties of an UI element on runtime. Across the API reference and the guides on Smartface, you will encounter two types of assigning a property to an UI element.
If you want to assign custom properties using the code, you can use component.dispatch
as follows:
function changeMargin(): void {
this.marginTop = 5; // Wrong. The property will be set but the UI will not be updated.
this.backgroundColor = Color.RED; // Wrong. The property will be set but the UI will not be updated.
this.dispatch({
type: "updateUserStyle",
userStyle: {
marginTop: 5,
backgroundColor: "#FF0000" // Note that Color.RED will not work here.
}
});
}
About differences of properties
When using direct assignment, you need to use their underlying property as a value. However, when using style you need to use string or number values since we are simulating to assign JSON variables.
For example, this will not work:
// DO NOT USE THIS CODE
this.dispatch({
type: "updateUserStyle",
userStyle: {
positionType: FlexLayout.PositionType.ABSOLUTE,
backgroundColor: Color.RED
}
});
Those variables are often an enum and will be equivalent to this:
// DO NOT USE THIS CODE
this.dispatch({
type: "updateUserStyle",
userStyle: {
positionType: 1 // Enum value of the PositionType.ABSOLUTE variable. It is used for different purposes in native.
backgroundColor: -65536 // Decimal representation of RED color in Android native.
}
});
Difference between direct assignment and class assignment
There are two ways to update UI elements on Runtime:
- Direct assignment
- Using dispatch
Let's look at this snippet. It will hide or show the given container on two different methods:
- Direct Assignment
- Dispatch
function hideWrapperLayout() {
this.flexLayout1.height = 0;
this.flexLayout1.visible = false;
this.flexLayout1.positionType = FlexLayout.PositionType.RELATIVE;
}
function showWrapperLayout() {
this.flexLayout1.height = 300;
this.flexLayout1.visible = true;
this.flexLayout1.positionType = FlexLayout.PositionType.ABSOLUTE;
}
function hideWrapperLayout() {
this.flexLayout.dispatch({
type: "updateUserStyle",
userStyle: {
height: 0,
visible: false,
positionType: "RELATIVE",
},
});
}
function showWrapperLayout() {
this.flexLayout.dispatch({
type: "updateUserStyle",
userStyle: {
height: 300,
visible: true,
positionType: "ABSOLUTE",
},
});
}
Two methods aim towards the same goal, hiding or showing the given layout.
However, using direct assignment is considered as anti-pattern and discouraged unless you are assigning an attribute. Refer here for updated list of attributes.
Smartface uses underlying Context renderer for their UI rendering and keeping class based structure. By directly assigning those, context will not be informed about the change, therefore might cause unexpected behaviours like incorrect positioning or not applying the changes.
function setLabel() {
this.label1.text = "Smartface"; // This is correct, text is an attribute
this.label1.width = 100; // This is anti pattern, width is not an attribute
// Use dispatch like this to update the context and width of the element
this.label1.dispatch({
type: "updateUserStyle",
userStyle: {
width: 100,
},
});
}