Toggle(开关)是一种常用的UI组件,用于在两种状态(不包含悬停、锁定)之间进行切换。
提示
本文章需要一定的 JSON UI 知识,建议了解绑定属性。
开关属性
创建开关
要创建一个开关,我们可以选择使用原版预设的开关。(以下将“原版预设的开关”简称为“预设开关”)
"test_toggle@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "toggle_name_1",
"$button_text": "toggle"
}
在示例中,使用$toggle_view_binding_name让绑定读取当前开关的状态。
提示
代码中的 "$toggle_state_binding_name": "#toggle_state" 用于防止代码报错,这是由于该变量在预设开关中没有声明。
现在,为某个控件添加绑定,让开关的状态转化为控件可见的状态。这样可以让控件在开关开启状态下显示该控件。
"test": {
"type": "label",
"text": "hello world",
"bindings": [
{
"binding_type": "view",
"source_control_name": "toggle_name_1",
"source_property_name": "#toggle_state",
"target_property_name": "#visible"
}
]
}
代码块中的source_control_name等于上方开关的$toggle_view_binding_name,这样才能把控件的可见性绑定为开关的状态。
提示
$toggle_view_binding_name不能与其他子控件名重复,否则绑定冲突,需要让变量值是唯一的。
更改开关外观
当你想要修改一个预设开关的外观时,你可以尝试使用下方的变量修改预设开关不同状态下的外观。
- $unchecked_control未启用
- $checked_control启用
- $unchecked_hover_control未启用 悬停
- $checked_hover_control启用 悬停
- $unchecked_locked_control未启用 锁定
- $checked_locked_control启用 锁定
- $unchecked_locked_hover_control未启用 锁定 悬停
- $checked_locked_hover_control启用 锁定 悬停
当你的开关没有禁用的需求,你可以不修改锁定状态的样式。
这些变量的值为控件,格式为namespace.control_name,namespace 是当前样式控件所在文件的命名空间(此处请不要忽略命名空间),control_name 是当前样式控件的控件名。我们只需要把不同样式的控件分别引用到这些变量中即可:
"test_toggle@common_toggles.light_text_toggle":{
"size": [30,20],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "toggle_name_1",
"$unchecked_control": "start.toggle_uncheck",
"$checked_control": "start.toggle_check",
"$unchecked_hover_control": "start.toggle_uncheck_hover",
"$checked_hover_control": "start.toggle_check_hover"
},
"toggle_uncheck@toggle_style":{"$toggle_image":"toggle_off"},
"toggle_check@toggle_style":{"$toggle_image":"toggle_on"},
"toggle_uncheck_hover@toggle_style":{"$toggle_image":"toggle_off_hover"},
"toggle_check_hover@toggle_style":{"$toggle_image":"toggle_on_hover"},
"toggle_style":{"type":"image","texture":"('textures/ui/' + $toggle_image)"}
开关组
开关组允许用户在不同的选项之间进行切换,不同于普通开关,这些选项都是互斥的。
在预设的开关中,可以使用$radio_toggle_group变量定义开关组。
"toggle_group@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "toggle_name_1",
"$button_text": "toggle",
"$radio_toggle_group": true,
"$toggle_name": "toggle_group_1"
}
示例中,$toggle_name可以定义预设开关所在的开关组。
在不同开关组之间,选项是互不影响的。因此,当前开关组的选项不会因为另外一个开关组而影响。
下方是同一个开关组,不同选项的示例:
"group_common@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$radio_toggle_group": true,
"$toggle_group_default_selected": 0,
"$toggle_name": "toggle_group_1"
},
"group_1@group_common":{
"$toggle_view_binding_name": "toggle_name_1",
"$button_text": "toggle_1",
"$toggle_group_forced_index": 0
},
"group_2@group_common":{
"$toggle_view_binding_name": "toggle_name_2",
"$button_text": "toggle_2",
"$toggle_group_forced_index": 1
}
在开关组每个选项中,$toggle_group_forced_index用于定义当前选项的索引。在 group_common 控件中,$toggle_group_default_selected变量用于定义开关组默认选中哪个索引的选项。(这些变量仅适用于预设开关,自行创建的控件可以参考上方的属性)
下方是不同开关组的示例:
"group_common@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$radio_toggle_group": true,
"$button_text": "toggle",
"$toggle_group_default_selected": 0,
"$toggle_group_forced_index": 0
},
"group_1@group_common":{
"$toggle_view_binding_name": "toggle_name_1",
"$toggle_name": "toggle_group_1"
},
"group_2@group_common":{
"$toggle_view_binding_name": "toggle_name_2",
"$toggle_name": "toggle_group_2"
}
在这个示例中,可以得知不同的开关组之间是不会影响的。
深入探究
开关真的只能用作控制控件的可见状态吗?
除了控制可见性之外,我们还可以使用绑定把开关状态的布尔值传递给某个硬编码。开关的状态等于布尔值。开关开启时为 true,关闭时为 false。接下来以下方示例深入探究:
"test_toggle@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "can_drag",
"$button_text": "toggle"
},
"drag_panel@common.button": {
"size": ["100%c","100%c"],
"sound_volume": 0,
"draggable": "both",
"layer": 100,
"prevent_touch_input": true,
"controls": [{"text":{"type":"label","text":"hello world"}}],
"bindings": [
{
"binding_type": "view",
"source_control_name": "can_drag",
"source_property_name": "#toggle_state",
"target_property_name": "#enabled"
}
]
}
在代码中,我们演示了开关间接控制拖动面板的拖动状态。
首先我们使用绑定把开关状态转化为enabled属性,再通过这个属性禁用拖动来实现效果。
问题是enabled属性是传播到子控件的,这可能导致子控件无法互动。解决办法也是有的,我们可以其他方法来控制拖动,不过,此文章不再过多展开赘述。
"test_toggle@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "hidden",
"$button_text": "toggle"
},
"test": {
"type": "panel",
"size": ["100%c","100%c"],
"layer": 100,
"alpha": 0,
"controls": [{"text":{"type":"label","text":"hello world"}}],
"bindings": [
{
"binding_type": "view",
"source_control_name": "hidden",
"source_property_name": "#toggle_state",
"target_property_name": "#propagateAlpha"
}
]
}
在代码中,我们另外演示了开关控制控件的不透明度传播,做到了视觉上的隐藏。
其他预设开关
在前面的示例中,通常是以 common_toggles 的开关作为示例。下方还有其他的预设开关,以供参考。
"toggle_control@settings_common.option_toggle_control": {
"size": [30,20],
"$option_binding_name": "#toggle_state"
// 此处可以使用 $unchecked_control 等变量定义开关的样式
},
"toggle@settings_common.option_toggle": {
// 可以使用下方变量移除选项文字
// "$show_option_label": false,
"$option_label": "测试",
"$control_name": "start.toggle_control",
"anchor_from": "bottom_middle",
"anchor_to": "bottom_middle"
},
"test": {
"type": "label",
"text": "hello world",
"bindings": [
{
"binding_type": "view",
"source_control_name": "start.toggle_control",
"source_property_name": "#toggle_state",
"target_property_name": "#visible"
}
]
}
这是 settings_common 中的预设开关。要注意的是$control_name变量的格式为namespace.control_name,namespace 是 toggle_control 控件所在文件的命名空间(不能忽略命名空间),control_name 是 toggle_control 控件的控件名。
代码中的 $option_binding_name 等于上方所说到的 $toggle_state_binding_name 变量,作用一致,都是为了防止变量未声明报错。
提示
绑定中的 source_control_name 要与 $control_name 的值一致,这样才能绑定到开关。
"toggle@common.toggle":{
"size": [30,20],
"$toggle_state_binding_name": "#toggle_state",
// 此处可以使用 $unchecked_control 等变量定义开关的样式
// 也可以使用 controls 属性定义开关的样式
// 例如:"controls": [{"unchecked":{}}]
},
"toggle_panel": { // 引用 toggle 的控件
"controls": [
{"toggle_name_1@start.toggle":{}}
]
},
"test": {
"type": "label",
"text": "hello world",
"bindings": [
{
"binding_type": "view",
"source_control_name": "toggle_name_1",
"source_property_name": "#toggle_state",
"target_property_name": "#visible"
}
]
}
这是 ui_common 中的预设开关。代码中的{"toggle_name_1@start.toggle":{}}子控件名用于 view 绑定,用于绑定的子控件名必须是唯一的,不可重复,否则无法绑定到指定开关上。
另外,common.toggle 的预设开关默认是没有外观样式的,需要自行定义样式。
代码示例
"test_toggle@common_toggles.light_text_toggle": {
"size": [100,30],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "toggle_name_1",
"$button_text": "toggle"
},
"test": {
"type": "label",
"text": "hello world",
"bindings": [
{
"binding_type": "view",
"source_control_name": "toggle_name_1",
"source_property_name": "#toggle_state",
"target_property_name": "#visible"
}
]
}
"test_toggle@common_toggles.light_text_toggle":{
"size": [30,20],
"$toggle_state_binding_name": "#toggle_state",
"$toggle_view_binding_name": "toggle_name_1",
"$unchecked_control": "start.toggle_uncheck",
"$checked_control": "start.toggle_check",
"$unchecked_hover_control": "start.toggle_uncheck_hover",
"$checked_hover_control": "start.toggle_check_hover"
},
"toggle_uncheck@toggle_style":{"$toggle_image":"toggle_off"},
"toggle_check@toggle_style":{"$toggle_image":"toggle_on"},
"toggle_uncheck_hover@toggle_style":{"$toggle_image":"toggle_off_hover"},
"toggle_check_hover@toggle_style":{"$toggle_image":"toggle_on_hover"},
"toggle_style":{"type":"image","texture":"('textures/ui/' + $toggle_image)"}