/** * @packageDocumentation * @module ui */ import { CustomToggleGroup } from "./CustomToggleGroup" const { property, ccclass, requireComponent, executionOrder, menu } = cc._decorator export enum ToggleSwitchType { active, animation } /** * @en * The toggle component is a CheckBox, when it used together with a ToggleGroup, * it could be treated as a RadioButton. * * @zh * Toggle 是一个 CheckBox,当它和 ToggleGroup 一起使用的时候,可以变成 RadioButton。 */ @ccclass @executionOrder(110) @menu('UI/CustomToggle') export class CustomToggle extends cc.Component { /** * @en * When this value is true, the check mark component will be enabled, * otherwise the check mark component will be disabled. * * @zh * 如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。 */ @property get isChecked() { return this._isChecked } set isChecked(value) { this._set(value) } set _resizeToTarget(value: boolean) { // if (value) { // this._resizeNodeToTargetNode(); // } } get _toggleContainer() { const parent = this.node.parent! if (parent instanceof cc.Node) { return parent.getComponent(CustomToggleGroup) } return null } /** * @en * If Toggle is clicked, it will trigger event's handler. * * @zh * Toggle 按钮的点击事件列表。 */ @property({ type: [cc.Component.EventHandler], tooltip: 'i18n:toggle.check_events' }) public checkEvents: cc.Component.EventHandler[] = [] @property(cc.Boolean) protected _isChecked = true @property([cc.Node]) protected onNodeList: cc.Node[] = [] @property([cc.Node]) protected offNodeList: cc.Node[] = [] @property({ type: cc.Enum(ToggleSwitchType) }) toggleSwitchType: ToggleSwitchType = ToggleSwitchType.active //是否關閉點擊事件 @property(cc.Boolean) isDoNotEmitToggle = false private toggleEventMap: Map = new Map([ [ToggleSwitchType.active, this.switchByActive.bind(this)], [ToggleSwitchType.animation, this.switchByAnimation.bind(this)] ]) protected _internalToggle() { if (this.isDoNotEmitToggle) { return } this.isChecked = !this.isChecked } protected _set(value: boolean, emitEvent = true) { if (this._isChecked == value) return this._isChecked = value const group = this._toggleContainer if (group && group.enabled && this.enabled) { if (value || (!group.anyTogglesChecked() && !group.allowSwitchOff)) { this._isChecked = true group.notifyToggleCheck(this as any, emitEvent) } } this.playEffect() if (emitEvent) { this._emitToggleEvents() } } // public playEffect() { this.toggleEventMap.get(this.toggleSwitchType)() } switchByActive() { this.onNodeList.forEach((node) => { node.active = this._isChecked }) this.offNodeList.forEach((node) => { node.active = !this._isChecked }) } switchByAnimation() { } /** * @en * Set isChecked without invoking checkEvents. * * @zh * 设置 isChecked 而不调用 checkEvents 回调。 * * @param value - 是否被按下 */ public setIsCheckedWithoutNotify(value: boolean) { this._set(value, false) } onEnable() { this.playEffect() if (!CC_EDITOR || CC_PREVIEW) { this.node.on(cc.Node.EventType.TOUCH_END, this._internalToggle, this) } } onDisable() { if (!CC_EDITOR || CC_PREVIEW) { this.node.off(cc.Node.EventType.TOUCH_END, this._internalToggle, this) } } public OnDestroy() { const group = this._toggleContainer if (group) { group.ensureValidState() } } protected _emitToggleEvents() { this.node.emit("toggle", this) if (this.checkEvents) { cc.Component.EventHandler.emitEvents(this.checkEvents, this) } } } /** * @en * Note: This event is emitted from the node to which the component belongs. * * @zh * 注意:此事件是从该组件所属的 Node 上面派发出来的,需要用 node.on 来监听。 * @event toggle * @param {Event.EventCustom} event * @param {Toggle} toggle - The Toggle component. */