开关

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不能与其他子控件名重复,否则绑定冲突,需要让变量值是唯一的。

更改开关外观

当你想要修改一个预设开关的外观时,你可以尝试使用下方的变量修改预设开关不同状态下的外观。

当你的开关没有禁用的需求,你可以不修改锁定状态的样式。

这些变量的值为控件,格式为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)"}